如何使用Golang进行自定义错误的包装与传递_Golang自定义错误包装与传递实践-Golang

Go 1.13+ 中 errors.Wrap 不兼容标准错误链,因其 Unwrap 返回私有结构体,导致 errors.Is/As 失效;应改用 fmt.Errorf(“%w”, err) 或自定义错误类型实现 Unwrap/Is/As。

为什么 errors.Wrap 不能直接用在 Go 1.13+ 的标准错误链里

Go 1.13 引入了 errors.Is 和 errors.As,但它们依赖底层错误是否实现了 Unwrap() 方法。而 github.com/pkg/errors.Wrap 返回的错误类型虽然有 Unwrap(),但它返回的是一个私有结构体,和标准库 fmt.Errorf 的行为不完全兼容——尤其当你混用 pkg/errors 和 fmt.Errorf("%w", err) 时,errors.Is 可能失效。

  • 如果你项目已升级到 Go 1.13+,优先用标准库的 fmt.Errorf("%w", err) 包装,不是 errors.Wrap
  • pkg/errors 的 Wrap 仍可工作,但无法被 errors.As 正确识别为“包装错误”,除非你手动实现 As 方法
  • 老项目迁移时,搜索所有 errors.Wrap 调用,替换为 fmt.Errorf("xxx: %w", err) 更安全

如何让自定义错误支持 Is 和 As 并保留上下文字段

纯包装(%w)只能传递错误链,但很多场景你需要附带结构化信息:如 HTTP 状态码、重试次数、请求 ID。这时不能只靠 fmt.Errorf,得自己实现错误类型。

  • 定义结构体时嵌入 error 字段,并实现 Unwrap() 返回它
  • 实现 Is(target error) bool 时,先检查自身是否匹配,再调用 errors.Is(wrapped, target)
  • 实现 As(target interface{}) bool 时,若目标是指向你自定义类型的指针,就做类型断言赋值;否则继续委托给包裹的错误
  • 不要在 Error() 方法里拼接 Unwrap().Error() ——这会破坏错误链的扁平性,fmt.Errorf 已帮你做了
type MyAPIError struct {
    Code    int
    ReqID   string
    Err     error
}

func (e *MyAPIError) Error() string { return fmt.Sprintf("API failed (code=%d, req=%s)", e.Code, e.ReqID) }
func (e *MyAPIError) Unwrap() error  { return e.Err }
func (e *MyAPIError) Is(target error) bool {
    if t, ok := target.(*MyAPIError); ok {
        return e.Code == t.Code && e.ReqID == t.ReqID
    }
    return errors.Is(e.Err, target)
}
func (e *MyAPIError) As(target interface{}) bool {
    if t, ok := target.(*MyAPIError); ok {
        *t = *e
        return true
    }
    return errors.As(e.Err, target)
}

在 HTTP handler 中包装错误时,为什么不能直接 return fmt.Errorf("failed to parse: %w", err)

HTTP handler 通常需要返回特定状态码和 JSON 错误体,但 fmt.Errorf 包装后的错误本身不含状态码语义。如果上层统一用 http.Error 处理,会导致所有错误都变成 500,掩盖了本应是 400 的参数错误。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 如何使用Golang进行自定义错误的包装与传递_Golang自定义错误包装与传递实践-Golang
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3997593+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3997594+
  • 本周更新: 0+
  • 最后更新: 2026-03-16