Go

What does this print? (Rules of recover)

Question 306HardGo 1.22 to 1.25
func helper() {
	if r := recover(); r != nil {
		fmt.Println("recovered:", r)
	}
}

func a() { defer helper(); panic("A") }             // helper IS the deferred func
func b() { defer func() { helper() }(); panic("B") } // helper called BY deferred func
func c() { defer recover(); panic("C") }             // recover deferred directly

func main() {
	a()
	fmt.Println("after a")
	b()
	fmt.Println("after b")
}

Output: recovered: A, after a, and then the program crashes with panic: B. recover stops a panic only when it is called directly by a deferred function while the goroutine is panicking. In a, helper is the deferred function, so it works. In b, helper is one call deeper, so recover returns nil and the panic continues. c fails too, because defer recover() makes recover itself the deferred call rather than a call made by a deferred function.

Other rules: outside a panic, recover returns nil. It works only in the same goroutine as the panic. After recovering, the function whose defer recovered returns normally to its caller (with named results set to whatever the defer assigned), and execution does not resume at the point of the panic.

More on Error Handling & panics

All 37 Error Handling & panics questions