参考:https://go101.org/quizzes/panic-recover-1.html
package main
import "fmt"
func ExamplePanicGo101_1() {
defer func() {
fmt.Print(recover()) // catch panic(1)
}()
defer func() {
defer fmt.Print(recover()) // catch panic(2)
defer panic(1)
recover() // no-op - B, should be called inside deferred function,
}()
defer recover() // no-op - A, should be called inside deferred function,
panic(2)
// Output:
// 21
}
测试通过。
问题:
no-op - A
是无操作的,因为它不是在延迟函数内部调用的,但是 no-op - B
是无操作的吗?由于它是在延迟函数内部调用的,所以我认为它应该捕获 panic(2)
,但没有。我想你可能错过了以下点
defer
:
每次执行“defer”语句时,调用的函数值和参数都会照常评估并重新保存,但不会调用实际函数。
所以执行时
defer fmt.Print(recover()) // catch panic(2)
defer panic(1)
recover() // no-op - B, should be called inside deferred function,
步骤是:
recover()
,并有效地评估 defer fmt.Print(2)
(因为 recover()
评估为 2
)。defer panic(1)
recover()
- nooop,因为没有活跃的恐慌panic(1)
fmt.Print(2)
(记住“由 F 延迟的任何函数都会照常执行”)以下示例可能会有所帮助:
package main
import "fmt"
func main() {
defer func() {
fmt.Println(recover()) // catch panic(1)
}()
defer func() {
fmt.Println("a")
defer fmt.Println(fmt.Println("a1")) // The "a1" will print between a and b (note `3 nil` will be printed later, this is the return from the inner fmt.Println)
defer fmt.Println(recover()) // catch panic(2)
fmt.Println("b")
defer panic(1)
fmt.Println("c")
recover() // no-op - B, should be called inside deferred function,
}()
defer recover() // no-op - A, should be called inside deferred function,
panic(2)
// Output:
// a
// a1
// b
// c
// 2
// 3 <nil>
// 1
}