Go func recover
你提到的理解误区在于 recover 的有效性。虽然 recover 是在 defer 语句中使用的,但它必须满足以下条件才能有效:
recover必须在一个defer调用的函数中直接执行。- 这个
defer调用的函数必须在panic发生后执行。
让我们更详细地解释为什么某些地方的 recover 无效。
代码分析
package main
import "fmt"
func test() {
defer func() {
fmt.Println(recover()) // 有效
}()
defer recover() // 无效!
defer fmt.Println(recover()) // 无效!
defer func() {
func() {
println("defer inner")
recover() // 无效!
}()
}()
panic("test panic")
}
func main() {
test()
}
详细解释
-
第一个
defer:defer func() {
fmt.Println(recover()) // 有效
}()这个
defer调用了一个匿名函数,并且在这个匿名函数内部直接调用了recover。当panic发生后,这个defer会在函数返回之前执行,因此recover能够捕获到panic。 -
第二个
defer:defer recover() // 无效!这里的
recover不是在一个defer调用的函数中直接执行的,而是在defer语句中立即执行的。也就是说,recover在panic发生之前就已经执行了,所以无法捕获到panic。 -
第三个
defer:defer fmt.Println(recover()) // 无效!类似于 第二个
defer,recover在defer语句中立即执行,而不是在defer调用的函数中执行。因此,recover在panic发生之前就已经执行了,所以无法捕获到panic。 -
第四个
defer:defer func() {
func() {
println("defer inner")
recover() // 无效!
}()
}()在这个例子中,虽然
recover是在defer调用的函数中执行的,但它是在嵌套的函数中执行的。只有在直接的defer调用的函数中,recover才能捕获到panic。嵌套的函数不能捕获到panic。