Golang 中的 defer、panic 和 recover 有什么关系?

在 Golang 中,defer、panic 和 recover 三个关键词关系密切,用于异常处理机制。

  • defer: defer 语句会将其后面跟随的语句进行延迟执行。在函数结束的时候,这些延迟调用的语句将按照逆序执行。defer 主要用于资源清理、文件关闭、解锁等操作。
  • panic: panic 可以在程序运行过程中引发一个异常,默认会终止当前运行goroutine。通常用于不可恢复的错误。
  • recover: recover 允许程序员控制一个panic,并恢复正常的执行。recover 只在defer调用的函数中有效。

他们的关系可以总结为:
defer statement 可以跟一个 panic 的recover语句一起使用,以允许panic被恢复。

如果没有recover语句与该defer一起使用,panic将继续通过调用栈传播。

示例代码:

func test() {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("recover in defer")
        }
    }()
    panic("panic in test()")
}

func main() {
    test()
    fmt.Println("main")
}
输出:
recover in defer
main

可以看到,由于在 defer 中使用了 recover 捕获了 panic,所以程序并未退出,而是继续运行,并输出 main。
如果去掉 defer 中的 recover,则程序运行 panic 后会退出,不会输出 main。

所以总结来说,三者关系是:

  • defer 用于延迟执行(资源清理等),并可以搭配 recover 捕获 panic
  • panic 主动触发异常,如果未被 recover 捕获,会退出程序
  • recover 用于捕获 panic,恢复正常程序执行