A panic normally unwinds the current function stack. If it reaches the top without being handled, the program terminates. Call `recover` inside a deferred function to retrieve the panic value and stop that unwinding. This lets you record or handle a failure instead of letting it crash the program. section 4.3.4
Trap a panic
```go package main import ( "errors" "fmt" ) func main() { defer func() { if value := recover(); value != nil { fmt.Printf("Trapped panic: %v (%T)\n", value, value) } }() yikes() } func yikes() { panic(errors.New("Something bad happened.")) } ``` The anonymous function is registered by `defer` and runs when `main` unwinds. Its call to `recover` obtains the value passed to `panic`; printing `%T` also shows its type. section 4.3.4
Put recovery on the stack that might panic. A goroutine has its own function stack: a panic in a request handler cannot unwind into the function that started that goroutine. In a connection handler, a deferred function can log a recovered panic and close the connection. If many tasks need the same protection, a helper can start each task inside a goroutine with its own deferred recovery function. section 4.3.5 section 4.3.5
Listing 4.20 Handling panics on a goroutine
func handle(conn net.Conn) {
defer func() { #1
if err := recover(); err != nil { #1
fmt.Printf("Fatal error: %s", err) #1
} #1
conn.Close() #1
}() #1
reader := bufio.NewReader(conn) #1
data, err := reader.ReadBytes('\n')
if err != nil {
fmt.Println("Failed to read from socket.")
}
response(data, conn)
}
func response(data []byte, conn net.Conn) {
conn.Write(data)
panic(errors.New("Pretend I’m a real error")) #2
}
The connection-handler listing places `recover` and connection cleanup in the same deferred function, on the goroutine's own stack. section 4.3.5
