go错误处理
Sentinel errors
哨兵模式,例如
if io == io.EOF
优缺点:需要导包,可能循环引用
Error Types
包含error以及其它信息的结构体
优缺点:需要导包,循环引用。但可得到更多的信息。比哨兵模式更好一点。
Opaque errors
黑盒策略,不关心具体错误类型,有错误则返回否则继续或根据是否具有某种行为(实现某种接口)判断是否重试。demo:
func fn() error {
x, err := bar.Foo()
if err != nil {
return err
}
// use x
return nil
}
//
type temporary interface { Temporary() bool}
func IsTemporary(err error) bool {
te, ok := err.(temporary)
return ok && te.Temporary()
}
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:
var err error
write := func(buf []byte) {
if err != nil {
return
}
_, err = w.Write(buf)
}
write(p0[a:b])
write(p1[c:d])
write(p2[e:f])
// and so on
if err != nil {
return err
}
法2:
type errWriter struct {
w io.Writer
err error
}
func (ew *errWriter) write(buf []byte) {
if ew.err != nil {
return
}
_, ew.err = ew.w.Write(buf)
}
更加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
- Author: DY
- Link: http://4fan.top/posts/go%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.