Venkatesh Laguduva
Venkatesh Laguduva

Reputation: 14338

Program recovered from panic does not exit as expected

Per my understanding, when a panic is recovered, I expected the program to exit and exhibit normal behaviour but it does not. Am I right to expect the last line to print "End of program"? it won't be printed in case of runtime error, is it?

package main

import (
    "fmt"
)

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("Cause of panic ==>>, %q\n", r)
        }
    }()
    f(3)
    fmt.Println("End of program")
}

func f(x int) {
    fmt.Printf("f(%d) is called.\n", x) //panic triggered when x==0
    // defer called in reverse order in case of panic
    defer fmt.Printf("defer %d\n", x+0/x)

    f(x-1)
}

Upvotes: 0

Views: 1163

Answers (2)

Marc
Marc

Reputation: 21035

The Go spec has a good description of what happens on panic / recover. A panic terminates the current function and all callers until the program exits. On the way, it executes all deferred functions. If one of those functions has a recover() and exits cleanly, the panic propagation is stopped.

In your case, panic terminates functions in this order: f(0), f(1), f(2), f(3), main(), running each function's deferred functions.

Your deferred function with recover() is located in main(). This means that main() is interrupted by the panic before it reaches the print statement, and the deferred function is called after.

If you want to catch the panic, recover, and continue on in main, you would need to add an intermediate function. eg:


func main() {
    handlePanic(3)
    fmt.Println("End of program")
}

func handlePanic(x int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("Cause of panic ==>>, %q\n", r)
        }
    }()
    f(x)
}

func f(x int) {
    fmt.Printf("f(%d) is called.\n", x) //panic triggered when x==0
    // defer called in reverse order in case of panic
    defer fmt.Printf("defer %d\n", x+0/x)

    f(x-1)
}

Upvotes: 2

Burak Serdar
Burak Serdar

Reputation: 51512

"End of program" will not be printed.

When a panic is detected, the function causing the panic immediately returns, as well as the function calling that function, etc. all the way to the function that calls recover. When that function returns and recovers, the program then continues as if no panic has happened.

In your case, main is the function that recovers. The panic is triggered at f(3) call, and the recovery takes place after main returns, bypassing the println.

Upvotes: 1

Related Questions