Go 语言项目开发实战
孔令飞
腾讯云专家工程师,前 Red Hat、联想云工程师
41030 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 61 讲
Go 语言项目开发实战
15
15
1.0x
00:00/00:00
登录|注册

19 | 错误处理(下):如何设计错误包?

思考错误包和错误码设计是否满足当前项目需求
定义iam-authz-server服务的错误码,并生成错误码文档
通过codegen工具解析错误码的注释
具体的错误码实现sample-code
基于github.com/pkg/errors包设计的github.com/marmotedu/errors错误包
错误包设计要点
GetUser函数
WriteResponse函数
Response结构体
错误码文档生成
错误码注册
实现ErrCode结构体
通用错误码定义
如何记录错误
性能对比
示例代码
withCode结构体
支持两种错误创建方式
支持As函数
提供Is方法
支持Wrap/Unwrap功能
支持不同的打印格式
支持错误堆栈
课后练习
总结
错误码实际使用方法示例
一个错误码的具体实现
错误包的实现
错误包需要具有哪些功能?
如何设计一个优秀的错误包

该思维导图由 AI 生成,仅供参考

你好,我是孔令飞。
在 Go 项目开发中,错误是我们必须要处理的一个事项。除了我们上一讲学习过的错误码,处理错误也离不开错误包。
业界有很多优秀的、开源的错误包可供选择,例如 Go 标准库自带的errors包、github.com/pkg/errors包。但是这些包目前还不支持业务错误码,很难满足生产级应用的需求。所以,在实际开发中,我们有必要开发出适合自己错误码设计的错误包。当然,我们也没必要自己从 0 开发,可以基于一些优秀的包来进行二次封装。
这一讲里,我们就来一起看看,如何设计一个错误包来适配上一讲我们设计的错误码,以及一个错误码的具体实现。

错误包需要具有哪些功能?

要想设计一个优秀的错误包,我们首先得知道一个优秀的错误包需要具备哪些功能。在我看来,至少需要有下面这六个功能:
首先,应该能支持错误堆栈。我们来看下面一段代码,假设保存在bad.go文件中:
package main
import (
"fmt"
"log"
)
func main() {
if err := funcA(); err != nil {
log.Fatalf("call func got failed: %v", err)
return
}
log.Println("call func success")
}
func funcA() error {
if err := funcB(); err != nil {
return err
}
return fmt.Errorf("func called error")
}
func funcB() error {
return fmt.Errorf("func called error")
}
执行上面的代码:
$ go run bad.go
2021/07/02 08:06:55 call func got failed: func called error
exit status 1
这时我们想定位问题,但不知道具体是哪行代码报的错误,只能靠猜,还不一定能猜到。为了解决这个问题,我们可以加一些 Debug 信息,来协助我们定位问题。这样做在测试环境是没问题的,但是在线上环境,一方面修改、发布都比较麻烦,另一方面问题可能比较难重现。这时候我们会想,要是能打印错误的堆栈就好了。例如:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了在Go项目开发中错误处理的重要性以及错误包的设计原则和功能。作者首先介绍了优秀的错误包需要具备的功能,包括支持错误堆栈、不同的打印格式、Wrap/Unwrap功能、Is方法、As函数以及两种错误创建方式。强调了错误堆栈的重要性,并提到了一些优秀的错误包,如`github.com/pkg/errors`包,并基于该包进行了二次封装,以支持错误码。文章还介绍了`github.com/marmotedu/errors`包的功能和性能测试结果,以及如何在实际生产环境中使用JSON格式打印日志。此外,还详细介绍了一个错误码的具体实现,包括通用错误码的定义、Coder结构体的实现以及错误码的注册和文档生成。总的来说,本文内容丰富,涵盖了错误包的设计原则、功能实现和性能对比,对于Go语言开发者来说具有很高的参考价值。读者可以从中了解如何设计一个优秀的错误包,以及错误包需要具备的功能,对于Go项目开发中的错误处理具有一定的指导意义。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言项目开发实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(32)

  • 最新
  • 精选
  • yandongxiao
    总结: 1. 为什么业务要开发自己的错误包?因为开源的error包中,没有业务错误码,不方便使用。 2. 如何区分内部错误和外部错误? 1. 将错误分为两部分,是一个非常好的设计,通过 error code 联系在一起 2. 将 error code, response code, external error message 注册到一张大表上 3. github.com/marmotedu/errors 包提供的 WitheCode 和 Wrap 方法,构建错误链(嵌套关系) 4. 通过 format 的各种形式,控制 error 的输出信息 3. 如何自动生成全局的错误码文档,方便排查问题和联调? 使用 codegen 工具。 4. 如何打印错误?只在错误最原始位置打印错误。

    作者回复: 总结的很全,很到位!

    2021-11-27
    10
  • pedro
    以推荐老师的项目给组里其它小伙伴,一起学习沉淀打磨为自己的实用标准,多谢老师

    作者回复: 感谢pedro支持

    2021-07-08
    8
  • 漂泊的小飘
    感觉需要看着源码再学一遍。。。

    作者回复: 老哥,加油!

    2021-07-28
    5
  • 树建
    文中提到withCode实现了format方法,但是看了errors.go中只查看withMessage实现了format

    作者回复: 就是 withMessage

    2022-05-05归属地:广东
    3
    3
  • 吹口哨yu
    withCode 没有实现 Format() 方法呀?

    作者回复: withMessage,我改下文章

    2022-07-13归属地:广东
    2
  • .
    看完了git中withCode错误的实现逻辑对于 WitCode需要分开cause和err 两个errors,很是迷惑。起初看完代码在猜想cause这个应该是为了递归打印,实现上个章节的”科学设计错误包“内容“ 错误码100101, 10: 服务。01: 某个服务下的某个模块。01: 模块下的错误码序号,每个模块可以注册 100 个错误。” 的功能,但是看了函数IsCode的逻辑,彻底懵逼了,code只对比了第一层的code就return,显然不是为了实现上一章节的内容,所以多个cause errors感觉是一个特别累赘的设计。 另外WithCode和WithStack 的入参都是error 接口。 如果一个error起初是go原生库的error, 先withCode再WithMessgge, 在执行err. Error() 会丢失打印不出完整的错误栈。这块是原本iam的就是业务设计就是如此吗?WithMessgge会直接决定了err. Error() 值,不管前面被With了多少次?

    作者回复: 是的

    2022-06-11归属地:广东
    2
  • 你赖东东不错嘛
    记录错误方式二:在err发生处打印了log,却依旧把err上抛,而最外层又对err进行了一次处理,这样可能导致日志里写了两份重复的err信息。望解惑!

    作者回复: 这个地方可以根据需要选择是否在上层直接返回err,还是再添加一些信息。 一般情况下直接返回err即可。但可能也有些业务逻辑需要在上层追加一些额外的信息,来帮助排障。

    2021-07-16
    3
    2
  • Geek_25f93f
    要写这么一个codegen工具应该要废很多时间

    作者回复: 一劳永逸

    2022-07-09归属地:广东
    1
  • Geek_c2089d
    func New(message string) error { return &fundamental{ msg: message, stack: callers(), } } 老师,想问一下errors/code.go 的包里面的callers()函数,哪里来的

    作者回复: 相同目录下,stack.go文件中

    2022-04-19
    1
  • 莫林
    老师能介绍一下如何适配gprc 的 status 响应吗?

    作者回复: 内容有点多,后面考虑出个加餐。

    2021-12-07
    1
收起评论
显示
设置
留言
32
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部