错误处理
error 接口
go
type error interface {
Error() string
}
任何实现 Error() string 的类型均可作为 error 返回。惯用哨兵错误(包级 var ErrXxx = errors.New("..."))表达固定种类错误。
构造与包装
go
import "errors"
err := errors.New("plain")
err := fmt.Errorf("user %d: %w", id, underlying)
%w将underlying包装进err,可用errors.Is/errors.As解包判断。- 非
%w则链断裂,errors.Is无法匹配底层。
判断
go
if errors.Is(err, io.EOF) { }
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
_ = pathErr.Path
}
errors.Is 沿包装链比较;errors.As 沿链查找可赋值的类型。
panic / recover
panic:停止当前 goroutine 正常执行,展开 defer;若未被recover,进程崩溃。recover:仅在 defer 中 调用有效,返回panic参数值。
编程错误(索引越界等)会 runtime panic。业务错误应返回 error,不要用 panic 作控制流。
多错误(Go 1.20+)
errors.Join(e1, e2, ...) 合并多个错误;Unwrap() []error 与 errors.Join 配套。
风格建议
- 错误字符串小写开头、无句号结尾,便于拼接
fmt.Errorf("context: %w", err)。 - 在边界(HTTP handler、main)记录日志并映射状态码;库函数倾向返回丰富
error而非直接打日志,由调用方决定。