Consider the following Golang code:
package main import "fmt" func printRecover() { r := recover() fmt.Println("Recovered:", r) } func main() { defer printRecover() panic("OMG!") }
This simple program successfully panics and recovers with the following output:
Recovered: OMG!
However, modifying the code to wrap printRecover() in another deferred function results in a different outcome:
package main import "fmt" func printRecover() { r := recover() fmt.Println("Recovered:", r) } func main() { defer func() { printRecover() }() panic("OMG!") }
In this case, the panic is not recovered, causing the program to crash:
Recovered: <nil> panic: OMG! goroutine 1 [running]: main.main() /tmp/sandbox898315096/main.go:15 +0x60
The explanation for this behavior lies in the way recover() works in Golang. According to the language specification:
The return value of recover is nil if any of the following conditions holds: - panic's argument was nil; - the goroutine is not panicking; - recover was not called directly by a deferred function.
In the first example, recover() is called directly by a deferred function, so it successfully retrieves the panic argument. In the second example, however, recover() is not called directly by a deferred function, but rather by a function that was itself called by a deferred function. As a result, recover() returns nil, and the panic is not recovered.
The above is the detailed content of Why Doesn\'t `recover()` Work in Nested Deferred Functions in Go?. For more information, please follow other related articles on the PHP Chinese website!