refer: 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
}
The test passes.
Questions:
no-op - A
is no-op, since it's not called inside deferred function, but how no-op - B
is no-op? Since it's called inside deferred function, I though it should catch the panic(2)
, but not.I think you may have missed the following point re defer
:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
So when executing
defer fmt.Print(recover()) // catch panic(2)
defer panic(1)
recover() // no-op - B, should be called inside deferred function,
the steps are:
recover()
and, effectively, defer fmt.Print(2)
(because recover()
evaluates to 2
).defer panic(1)
recover()
- noop as there is no active panicpanic(1)
fmt.Print(2)
(remember that "Any functions deferred by F are then executed as usual")The following example may help:
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
}