Go🔧Core Languagebeginner
Panic and Recover
Go · Core Language · Run with go run
Explanation
`panic` stops normal execution and begins unwinding the stack, running deferred functions along the way. `recover`, called inside a deferred function, stops the unwinding and returns the panic value — letting a program regain control. Go's convention is to use errors for expected failures and reserve `panic` for truly unrecoverable situations (programmer bugs, impossible states).
Real-World Scenario
An HTTP server wraps each request handler in a deferred `recover`. If a handler panics (e.g. a nil-pointer dereference), `recover` catches it, logs the stack, and returns a 500 response — one bad request doesn't crash the whole server.
Quick Snippet
snippet.go
func safeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered: %v", r)
}
}()
result = a / b // panics if b == 0
return result, nil
}
r, err := safeDivide(10, 0)
fmt.Println(r, err) // 0 recovered: runtime error: integer divide by zeroFull Example
panic_recover.go
// Compile: go run panic_recover.go
// Output:
// 10 / 2 = 5, err=<nil>
// 10 / 0 = 0, err=recovered: runtime error: integer divide by zero
// program continues normally
package main
import "fmt"
func safeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered: %v", r)
}
}()
result = a / b // panics when b == 0
return result, nil
}
func main() {
r1, err1 := safeDivide(10, 2)
fmt.Printf("10 / 2 = %d, err=%v\n", r1, err1)
r2, err2 := safeDivide(10, 0)
fmt.Printf("10 / 0 = %d, err=%v\n", r2, err2)
fmt.Println("program continues normally")
}
Run command
go run panic_recover.go