go错误处理
Sentinel errors
哨兵模式,例如
if io == io.EOF
优缺点:需要导包,可能循环引用
Error Types
包含error以及其它信息的结构体
优缺点:需要导包,循环引用。但可得到更多的信息。比哨兵模式更好一点。
Opaque errors
黑盒策略,不关心具体错误类型,有错误则返回否则继续或根据是否具有某种行为(实现某种接口)判断是否重试。demo:
1 | func fn() error { |
pkg/errors
携带一个message并可返回原始error以进行Sentinel errors比较的库:github.com/pkg/errors
可避免在多个层多次处理eror
go1.13标准库的升级
https://www.flysnow.org/2019/09/06/go1.13-error-wrapping.html
- errorf %w –>不丢失原error的wrap error。
- Unwrap 解一层wrap error
- Is wrap chain中是否包含
- As error转换(断言)
rob pike:Errors are values
法1:
1 | var err error |
法2:
1 | type errWriter struct { |
更加cleaner的法1,且可以反复使用,记录累计字节数等
但无法知道在出错前出现了执行了多少。通常情况下是够用的(多数情况下只需要在最后检查是否全部ok)。
关于Go中错误和异常的思考
不会终止程序逻辑运行的归类为错误,会终止程序逻辑运行的归类为异常。
个人思考
web后端dao,controller层次中的错误处理:
场景:dao层返回部分需要特别捕捉的错误
fmt.Errorf(“dao read something err: %w\n”,err)
中间层检测调用层返回是否error,如果error则直接返回。在本层出现error则返回fmt.Errorf(“相关说明 + 相关参数%v+ %w”,p,err)。只在controller层打印日志。如有其它判断可在相关层借助Is/As/Wrap等函数处理判断。
参考
https://qcrao.com/2019/09/18/golang-error-break-through/#Unwrap
https://go.dev/blog/errors-are-values
https://www.zhihu.com/question/27158146