1、原生错误处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义:
1 | go复制代码type error interface { |
我们可以在编码中通过实现 error 接口类型来生成错误信息。
函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:
1 | go复制代码func Sqrt(f float64) (float64, error) { |
在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:
1 | go复制代码result, err:= Sqrt(-1) |
2、开源error包
github.com/pkg/errors包在原生error包基础上增加了以下常用的功能:
- 可以打印error的堆栈信息:打印错误需要%+v才能详细输出
- 使用Wrap或Wrapf,初始化一个error
- 使用errors.WithMessage可以在原来的error基础上再包装一层,包含原有error信息
- errors.Is,用于判断error类型,可根据error类型不同做不同处理
- errors.As,用于解析error
具体使用案例见全局错误处理一节。
3、工程中错误处理
3.1 需求整理
- 自定义error信息,并进行编码整理
- controller层可以判断自定义error类型,最终判断是按info处理,还是按error处理
- 可以打印error初始发生的位置(获取error的调用栈)
- 确认当前系统定位:
- 用户,获取TagMessage
- 上游服务,需要错误码映射
- 日志监控、监控TagMessage
下面在一个工程化的项目中利用github.com/pkg/errors
包,完整实现一套的错误处理机制
3.2 方式一:Map保存错误码与Message的映射
3.2.1 定义错误信息
新建error_handler.go
1 | go复制代码package error_handle |
3.3 自定义Error使用
新建测试文件:error_handler_test.go
1 | go复制代码package error_handle |
3.3 方式二:借助generate简化代码(建议使用)
方式一维护错误码与错误信息的关系较为复杂,我们可以借助go generate来自动生成代码。
3.3.1 安装stringer
stringer不是Go自带工具,需要手动安装。执行如下命令即可
1 | go复制代码go get golang.org/x/tools/cmd/stringer |
3.3.1 定义错误信息
新建error_handler.go。在error_handler中,增加注释//go:generate stringer -type ErrCode -linecomment。执行go generate,会生成新的文件
1 | go复制代码package error_handle |
3.3.2 自定义Error使用
新建测试文件:error_handler_test.go
1 | go复制代码package error_handle |
4 总结
CustomError
作为全局error
的底层实现,保存具体的错误码和错误信息;CustomError
向上返回错误时,第一次先用Wrap
初始化堆栈,后续用WithMessage
增加堆栈信息;- 从
error
中解析具体错误时,用errors.As
提取出CustomError
,其中的错误码和错误信息可以传入到具体的API接口中; - 要判断
error
是否为指定的错误时,用errors.Is
+Handler Error
的方法,处理一些特定情况下的逻辑;
Tips:
- 不要一直用errors.Wrap来反复包装错误,堆栈信息会爆炸,具体情况可自行测试了解
- 利用go generate可以大量简化初始化Erro重复的工作
github.com/pkg/errors
和标准库的error
完全兼容,可以先替换、后续改造历史遗留的代码- 一定要注意打印
error
的堆栈需要用%+v
,而原来的%v
依旧为普通字符串方法;同时也要注意日志采集工具是否支持多行匹配
我是简凡,一个励志用最简单的语言,描述最复杂问题的新时代农民工。求点赞,求关注,如果你对此篇文章有什么疑惑,欢迎在我的微信公众号中留言,我还可以为你提供以下帮助:
- 帮助建立自己的知识体系
- 互联网真实高并发场景实战讲解
- 不定期分享Golang、Java相关业内的经典场景实践
我的博客:besthpt.github.io/
微信公众号:”简凡丶”
本文转载自: 掘金