panic, recover, and Failure Modes
Overview
panic and recover handle unrecoverable errors. Unlike normal errors, panics crash the program unless recovered.
When to Panic
✅ Appropriate: - Programmer errors (bugs) - Impossible conditions - Failed invariants - During initialization
❌ Avoid for: - Expected errors (file not found, network timeout) - User input validation - Anything recoverable
Panic
func divide(a, b int) int {
if b == 0 {
panic("division by zero") // Terminates program
}
return a / b
}Common Panic Sources
// nil pointer dereference
var p *int
*p = 1 // panic
// Index out of range
arr := []int{1, 2}
arr[10] // panic
// Invalid type assertion
var i interface{} = "string"
i.(int) // panicRecover
Recover catches panics in deferred functions:
func safeCall() (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic recovered: %v", r)
}
}()
dangerousOperation()
return nil
}HTTP Server Pattern
func handler(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("panic: %v\n%s", err, debug.Stack())
http.Error(w, "Internal Server Error", 500)
}
}()
// Handle request
}Panic vs Error
// Return error for expected failures
func ReadFile(name string) ([]byte, error) {
if !exists(name) {
return nil, ErrNotFound // Expected case
}
// ...
}
// Panic for bugs
func MustCompile(pattern string) *Regexp {
r, err := Compile(pattern)
if err != nil {
panic(err) // Invalid pattern is programmer error
}
return r
}Summary
| Keyword | Purpose |
|---|---|
panic |
Unrecoverable error (crash) |
recover |
Catch panic in defer |
error |
Expected, recoverable failures |
| Use panic for | Use error for |
|---|---|
| Bugs | Expected failures |
| Invariant violations | User/external input |
| Initialization failures | I/O, network errors |