panic
- panic 用于不可以恢复的错误
- panic 退出前会执行 defer 指定的内容
panic vs. os.Exit
- os.Exit 退出时不会调用 defer 指定的函数
- os.Exit 退出时不输出当前调用栈信息
测试实例 1
func TestPanicVsExit(t *testing.T) {
defer func() {
fmt.Println("Finally!")
}()
fmt.Println("Start")
panic(errors.New("Something wrong!")) // panic 退出后输出一大串调用栈信息
//os.Exit(-1) // 直接退出
}
注意: 运行 panic
时输出 Finally!,而运行 os.Exit
时直接就退出了。
recover
在 defer 里面增加一个 recover,用于恢复
defer func() {
if err := recover(); err != nil {
// 恢复错误
}
}()
测试实例 2
func TestPanicVsExit(t *testing.T) {
defer func() {
if err := recover(); err != nil {
fmt.Println("recover from ", err)
}
}()
fmt.Println("Start")
panic(errors.New("Something wrong!")) // panic 退出后输出一大串调用栈信息
//os.Exit(-1) // 直接退出
}
// 输出
=== RUN TestPanicVsExit
Start
recover from Something wrong!
--- PASS: TestPanicVsExit (0.00s)
PASS
最常见的『错误恢复』
defer func() {
if err := recover(); err != nil {
log.Error("recovered panic", err)
}
}()
这样的错误恢复,仅仅只是记录了错误,或者干脆直接忽略掉了。
当心!recover 成为恶魔
- 形成僵尸服务进程,导致 health check【往往是检查这个进程是否存在】 失效
- "Let's it crash!" 往往是我们恢复不确定性错误最好的办法【程序自己崩溃掉,让守护进程帮忙重启程序】