Hi, everybody. Please, help me to solve this problem. There is a snippet.
I don’t understand why capturePanicY() inside anonymous function does not recover. Why the result of recover() inside capturePanicY is nil?
package main
import (
"fmt"
)
func capturePanicX() {
if v := recover(); v != nil {
fmt.Println("X recovered")
}
}
func capturePanicY() {
if v := recover(); v != nil {
fmt.Println("Y recovered")
}
}
func main() {
defer capturePanicX()
defer func() { capturePanicY() }()
panic("just do it")
}
// X recovered
One thing to note however, is that even if you called defer capturePanicX() twice, it would still only recover once, since once a function panics, it will call it’s deferred functions normally, but after calling the first recover, there is no longer a panic to recover from in the second defer statement since it’s already been recovered.
As for the reason why it won’t recover even if you only called defer func() { capturePanicY() }() by itself, here is a sentence from the article above: Recover is only useful inside deferred functions. During normal execution, a call to recover will return nil and have no other effect., so in this case I believe the deferred function gets executed normally, but then inside it you are calling a different function in it’s own stack with normal execution, which therefore has no connection with the main function to help it recover.
The answer is a bit hidden in the Recover section of Effective Go:
Because recover always returns nil unless called directly from a deferred function, deferred code can call library routines that themselves use panic and recover without failing.
(Scroll down to the fifth paragraph - the second one after the first code snippet - to find this statement.)