Go语言错误和异常处理 | 青训营笔记

89 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第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的函数中生效