在 Go 语言中,defer, panic 和 recover 是三个用于处理错误和异常的重要关键字。
defer
defer 关键字用于确保一个函数调用在程序执行结束后会被调用,无论函数是否出现错误。它通常用于清理资源,如关闭文件、解锁互斥锁等。
func foo() {
file, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
// 确保文件在函数结束时关闭
defer file.Close()
// 继续处理文件...
}
在这个例子中,file.Close() 会在 foo() 函数结束时被调用,无论函数是否正常结束还是因为错误而返回。
panic
panic 函数用于生成一个运行时错误,它会停止当前函数的执行,并开始回溯(unwinding)过程,即运行在当前 Goroutine 中被延迟(deferred)的函数,然后返回到 Goroutine 的调用者。这个过程会一直持续,直到当前 Goroutine 中的所有函数都返回为止,然后程序会终止。
func foo() {
// ...
panic("something went wrong")
// ...
}
在这个例子中,当 panic 被调用时,它会立即停止 foo 函数的执行,并开始运行被延迟的函数(如果有的话)。
recover
recover 函数用于捕获 panic 异常。如果没有发生 panic,调用 recover 会返回 nil,否则它会捕获 panic 的值,让程序恢复正常执行。
recover 只在被 defer 调用的函数中有效。在正常的执行过程中,调用 recover 会不起作用。
func foo() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in foo", r)
}
}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")
}
func g(i int) {
if i > 3 {
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v", i))
}
defer fmt.Println("Defer in g", i)
fmt.Println("Printing in g", i)
g(i + 1)
}
在这个例子中,当 g 函数在 i > 3 时调用 panic,执行过程会立即停止,然后运行 g 和 foo 中的被 defer 调用的函数。在 foo 的 defer 函数中,recover 被调用并捕获 panic 的值,然后打印出一个消息,并让程序恢复正常执行。
理解 defer, panic 和 recover 是编写 Go 程序的重要部分,它们提供了一种强大的控制流程的机制,可以用来处理错误和异常情况。
推荐阅读: