The cost of Go's panic and recover
Exceptions / panics as control flow
- Some participants defend using exceptions (or panics) to short‑circuit deep recursion or search, arguing the alternative is manually threading booleans or error flags through every stack frame.
- Others counter that panics in Go are explicitly not meant as general control flow or error propagation, unlike typical exception systems.
Go’s error handling ergonomics
- Widespread frustration with
if err != nilboilerplate; some feel early promises that higher‑level patterns would emerge never materialized. - Others defend it as explicit, legible control flow, preferring it over “magic” constructs or heavily abstracted error monads.
- There’s disagreement on community culture: some see resistance to acknowledging flaws (generics, errors); others say the ecosystem is actively exploring better error syntaxes and patterns.
Semantics and use of panic/recover
- Strong view from several commenters: panics are for truly unrecoverable/buggy states (nil deref, impossible invariants), not normal failures like I/O errors;
panicused like exceptions is called an antipattern. - Counter‑view: many real systems prefer to catch panics at boundaries, log/emit telemetry, and continue serving other work; killing the whole process is often seen as too harsh.
- Debate over whether “unrecoverable” conditions really exist in most software, and how that relates to concepts like the halting problem.
Where recover() is actually used
- Many report rarely using
recoverdirectly; common patterns are:- HTTP or gRPC middleware to convert panics into 500s and logs.
- Wrapping goroutines to prevent a single request/task panic from crashing the process.
- Parser implementations and some stdlib components that still use panic/recover internally.
- Pain point: no global catch‑all for panics across goroutines; you must wrap each goroutine or handle it at the process/container level.
Go vs Rust and other models
- Rust’s
Result/Optionplus?are praised for eliminating silent error‑ignoring, though some argue the functional style (map,or_else) feels too abstract for many teams. - Go’s ability to ignore error returns (especially via multiple assignment quirks) is seen as dangerous; linters help but are not universally enforced.
Performance and best practices
- Some claim that in certain patterns, panic+recover at a high level can outperform error checks at every call.
- Several commenters propose practical rules:
- Only
panicinmainor at startup, or provide pairedFoo/MustFooAPIs. - Centralize recovery for request handlers and goroutine entrypoints; otherwise, return errors and wrap them with contextual messages.
- Only