A panic is designed to crash the application which is the default behaviour. However, if you want to prevent this from happening and let your application carry on running as if nothing has happened you will have to use recover function. The rule is, recover from panics only if you meant to. In short, don't recover every panic by default. Instead, selectively recover by checking the panic type. Note: There is no recovery for conditions such as the application running out of memory.


Examples


Panic without recover


As shown below, the application crashed.


func main() {
fmt.Println("main: begin")

panic("Main function panicked!")

fmt.Println("main: end")
}

// Output:
// main: begin
// panic: Main function panicked!
//
// goroutine 1 [running]:
// main.main()
// /Users/mysql/Server/Go/src/github.com/inanzzz/client/cmd/client/main.go:4 +0xb3
// exit status 2

Recovering from all panics


As seen below, the application recovered from panic and didn't crash.


func main() {
defer func() {
if p := recover(); p != nil {
fmt.Println("main: recovered from panic")
}
}()

fmt.Println("main: begin")

panic("Main function panicked!")

fmt.Println("main: end")
}

// Output:
// main: begin
// main: recovered from panic

Selectively recover from panics


As seen below, the application recovered from good panic type but not the others.


type good struct {}
type bad struct {}

func main() {
defer func() {
switch p := recover(); p {
case nil:
case good{}:
log.Printf("recovered from %T\n", p)
case bad{}:
panic(p)
default:
panic(p)
}
}()

fmt.Println("main: begin")

//panic(good{})
//panic(bad{})
//panic("something else")

fmt.Println("main: end")
}

// Output for no panic at all.
// main: begin
// main: end

// Output when panic(good{}) is enabled.
// main: begin
// 2020/01/10 22:27:54 recovered from main.good

// Output when panic(bad{}) is enabled.
// main: begin
// ...
// /Users/inanzzz/Server/Go/src/github.com/inanzzz/client/cmd/client/main.go:11 +0xda
// ...
// exit status 2

// Output when panic("something else") is enabled.
// main: begin
// ...
// /Users/inanzzz/Server/Go/src/github.com/inanzzz/client/cmd/client/main.go:13 +0xda
// ...
// exit status 2