7.2 panic 和 recover
peter 196 3

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!" 往往是我们恢复不确定性错误最好的办法【程序自己崩溃掉,让守护进程帮忙重启程序】
预览图
评论区

索引目录