Chapter 12 - Recovering from Failure
Exercise 2: panic
and recover
Go through the following code samples, and predict what their output will be. No need to predict all the details of the stack traces; focus on determining which fmt.Println
calls will get made, and in what order.
Solution
Example 1
package main
import "fmt"
func main() {
fmt.Println("a")
panic("oh no")
// This call never gets made.
fmt.Println("b")
}
Output:
a
panic: oh no
goroutine 1 [running]:
main.main()
/tmp/sandbox493149858/prog.go:7 +0xa0
Example 2
package main
import "fmt"
func myFunction() {
// Even though the next line panics, this call gets
// made when myFunction exits.
defer fmt.Println("b")
panic("oh no")
}
func main() {
fmt.Println("a")
myFunction()
}
Output:
a
b
panic: oh no
goroutine 1 [running]:
main.myFunction()
/tmp/sandbox836036355/prog.go:7 +0xa0
main.main()
/tmp/sandbox836036355/prog.go:12 +0xa0
Example 3
package main
import "fmt"
func myFunction() {
panic("oh no")
// This call is never made because `myFunction`
// exits as soon as the program panics.
fmt.Println(recover())
}
func main() {
fmt.Println("a")
myFunction()
fmt.Println("b")
}
Output:
a
panic: oh no
goroutine 1 [running]:
main.myFunction()
/tmp/sandbox950318916/prog.go:6 +0x40
main.main()
/tmp/sandbox950318916/prog.go:12 +0xa0
Example 4
package main
import "fmt"
func otherFunction() {
// This runs when the deferred function call is made.
fmt.Println("c")
// This recovers from the panic and prints the panic
// message.
fmt.Println(recover())
}
func myFunction() {
// This call gets made when myFunction panics.
defer otherFunction()
panic("oh no")
// Execution does not resume here, because this
// function exited due to the panic.
fmt.Println("d")
}
func main() {
fmt.Println("a")
myFunction()
// Execution resumes here after recovering.
fmt.Println("b")
}
Output:
a
c
oh no
b
Because the program recovered from the panic, it doesn’t exit early, and so no stack trace is printed.