这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记
简单错误
简单的错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误
优先使用 errors.New 来创建匿名变量来直接表示简单错误
如果有格式化的需求,使用 fmt.Errorf
对于复杂的错误,有时候并不能简单描述,应该如何处理?
错误的包装提供了一个error嵌套另一个error的能力,生成一个error的跟踪链,同时结合错误的判定方法来确认调用链中是否有关注的错误出现。这个能力的好处是每一层调用方可以补充自己对应的上下文,方便跟踪排查问题,确定问题的根本原因在哪里
在fmt.Errorf中使用: %w关键字来将一个错误wrap至其错误链中
错误判定
判断一个错误是否为特定错误,使用errors.Is
还有一个errors.As
方法,它和is的区别在于as会提取出调用链中指定类型的错误,并将错误赋值给定义好的变量,方便后续处理
panic/recover
panic
Go语言中目前(Go1.12)是没有异常机制,但是使用panic/recover
模式来处理错误。 panic
可以在任何地方引发,但recover
只有在defer
调用的函数中有效。
在Go中,比错误更严重的就是panic,它的出现表示程序无法正常工作了,在使用时有以下几点应该注意:
- 不建议在业务代码中使用panic。因为panic发生后,会向上传播至调用栈顶,如果当前goroutine中所有 deferred 函数都不包含recover就会造成整个程序崩溃。
- 若问题可以被屏蔽或解决,建议使用error代替panic
- 特殊地,当程序启动阶段发生不可逆转的错误时,可以在init或main函数中使用panic。因为在这种情况下,服务启动起来也不会有意义。
recover
若程序运行期间引发了panic
导致程序崩溃,异常退出了。这个时候我们就可以通过recover
将程序恢复回来,继续往后执行。
recover()
必须搭配defer
使用。defer
一定要在可能引发panic
的语句之前定义。- 嵌套无法生效
- 只能在当前
goroutine
生效
总结
error
尽可能提供简明的上下文信息链,方便定位问题panic
用于真正异常的情况recover
生效范围,在当前goroutine
的被defer
的函数中生效