godeferred-execution

Why does `defer recover()` not catch panics?


Why does a call to defer func() { recover() }() successfully recover a panicking goroutine, but a call to defer recover() not?

As an minimalistic example, this code doesn't panic

package main

func main() {
    defer func() { recover() }()
    panic("panic")
}

However, replacing the anonymous function with recover directly panics

package main

func main() {
    defer recover()
    panic("panic")
}

Solution

  • The Handling panic section mentions that

    Two built-in functions, panic and recover, assist in reporting and handling run-time panics

    The recover function allows a program to manage behavior of a panicking goroutine.

    Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing.

    When the running of deferred functions reaches D, the return value of D's call to recover will be the value passed to the call of panic.
    If D returns normally, without starting a new panic, the panicking sequence stops.

    That illustrates that recover is meant to be called in a deferred function, not directly.
    When it panic, the "deferred function" cannot be the built-in recover() one, but one specified in a defer statement.

    DeferStmt = "defer" Expression .
    

    The expression must be a function or method call; it cannot be parenthesized.
    Calls of built-in functions are restricted as for expression statements.

    With the exception of specific built-in functions, function and method calls and receive operations can appear in statement context.