-1
package main

import "fmt"

func myRecover() {
    if r := recover(); r != nil {
        fmt.Println(r)
    }
}

func main() {
    defer func() {
        myRecover()
    }()
    panic("The gas price is skyrocketing!")
}

The code above can not recover from the panic somehow the code below can.

package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println(r)
        }
    }()
    panic("The gas price is skyrocketing!")
}

It is so confusing. I want to know why.

  • perhaps call panic from the deferred function https://stackoverflow.com/questions/58443138/defer-func-not-recover – jspcal Jun 16 '22 at 21:10
  • I know the doc says we need to call recover() directly from the deferred function. I want to know why this happens? How panic is propagated so that a function called by a deferred function can not perceive a panic? – Wang Honghui Jun 17 '22 at 06:13

1 Answers1

1

The specification says:

The return value of recover is nil if any of the following conditions holds:

  • ...
  • recover was not called directly by a deferred function.

In the first example, recover is not called directly by the deferred function. The recover function always returns nil in this case.

You can use myRecover by deferring the function directly.

func main() {
    defer myRecover()
    panic("The gas price is skyrocketing!")
}
  • It's odd in this case that the first code example will compile at all. Surely if a `recover()` call outside of any `defer` block is always `nil`, there is no reason to allow that code to exist, and the compiler could refuse to compile it? – user229044 Jun 16 '22 at 21:21
  • Ah, never mind. It's so that `func foo() { x := recover() }; ... defer foo()` works as intended. The problem OP is having is that `defer func() { foo() }` doesn't work, but if they'd just typed `defer foo()` this would work fine. – user229044 Jun 16 '22 at 21:25