Panic and recover
Reserve panic for unrecoverable invariants and internal programmer errors, not normal control flow.
Canonical guidance
- panic for impossible states, broken invariants, or initialization failures that must abort
- return errors for expected operational failures
- recover only at boundaries that can convert a panic into a controlled failure
Use when
- deciding between
panicanderror - hardening process or request boundaries
Avoid
- panic for validation failures
- recover everywhere
- using panic as a substitute for branching
Preferred pattern
func handler(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
}
}()
serve(w, r)
}
Anti-pattern
if err != nil {
panic(err)
}
Explanation: This anti-pattern is tempting because panic is concise, but expected failures deserve explicit control flow and caller-visible error handling.
Why
- panic unwinds control flow aggressively
- most failures in real systems are expected enough to deserve explicit error handling
Sources
- Defer, Panic, and Recover - Andrew Gerrand