godefer-keyword

When a recover() is no-op?


refer: https://go101.org/quizzes/panic-recover-1.html

package main

import "fmt"

func ExamplePanicGo101_1() {
    defer func() {
        fmt.Print(recover()) // catch panic(1)
    }()

    defer func() {
        defer fmt.Print(recover()) // catch panic(2)
        defer panic(1)
        recover() // no-op - B, should be called inside deferred function,
    }()

    defer recover() // no-op - A, should be called inside deferred function,
    panic(2)
    // Output:
    // 21
}

The test passes.

Questions:


Solution

  • I think you may have missed the following point re defer:

    Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.

    So when executing

    defer fmt.Print(recover()) // catch panic(2)
    defer panic(1)
    recover() // no-op - B, should be called inside deferred function,
    

    the steps are:

    The following example may help:

    package main
    
    import "fmt"
    
    func main() {
        defer func() {
            fmt.Println(recover()) // catch panic(1)
        }()
    
        defer func() {
            fmt.Println("a")
            defer fmt.Println(fmt.Println("a1")) // The "a1" will print between a and b (note `3 nil` will be printed later, this is the return from the inner fmt.Println)
            defer fmt.Println(recover())         // catch panic(2)
            fmt.Println("b")
            defer panic(1)
            fmt.Println("c")
            recover() // no-op - B, should be called inside deferred function,
        }()
    
        defer recover() // no-op - A, should be called inside deferred function,
        panic(2)
        // Output:
        // a
        // a1
        // b
        // c
        // 2
        // 3 <nil>
        // 1
    }