Golang / Golang Internals and Memory Management Interview Questions
How do panic and recover work in Go and when should you use them?
panic stops the normal execution of the current goroutine, unwinds the stack calling all deferred functions, and propagates up until it reaches the top of the goroutine's stack — at which point the runtime prints a stack trace and terminates the program. recover can intercept a panic but only inside a deferred function.
// Basic panic â causes runtime abort with stack trace func mustPositive(n int) int { if n <= 0 { panic(fmt.Sprintf("expected positive, got %d", n)) } return n } // recover â MUST be called inside a deferred function func safeDiv(a, b int) (result int, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("recovered from panic: %v", r) } }() result = a / b // panics if b == 0 return } r, err := safeDiv(10, 0) fmt.Println(r, err) // 0 recovered from panic: runtime error: integer divide by zero // recover() returns nil if not panicking // It cannot recover a panic from a DIFFERENT goroutine go func() { panic("goroutine panic") // crashes the whole program }() // When to use panic vs error: // panic â unrecoverable programming errors (index out of bounds, nil deref) // or internal invariant violations that should never happen // error â expected failure conditions (file not found, network timeout, bad input) // Libraries should NEVER let panics propagate to callers // Use recover at the public API boundary to convert to errors
The canonical use of panic/recover in Go is the library boundary pattern: a library may use panic internally for control flow (e.g., a parser that panics on syntax error deep in a call stack), but the exported function wraps the entire body in a deferred recover and converts the panic to an error value. This keeps the panic/recover internal and never surprises callers.
More Related questions...