Go

When is it appropriate to panic instead of returning an error?

Question 305MediumGo 1.22 to 1.25

Panic when there is a programmer error or an impossible state that the caller can't reasonably handle:

  • Violated invariants, such as an unreachable default in an exhaustive switch, or a nil dependency passed to a constructor.
  • Must helpers for static inputs at initialization: regexp.MustCompile, template.Must. The input is a constant, so failure is a bug.
  • Failed startup when the program can't run at all. Even then, log.Fatal or returning an error from run() is often cleaner.

Don't panic for anything that can happen in normal operation: bad user input, I/O, network or not-found conditions. A library should almost never let a panic escape its public API.

func MustParse[T any](s string, parse func(string) (T, error)) T {
	v, err := parse(s)
	if err != nil {
		panic(fmt.Sprintf("MustParse(%q): %v", s, err))
	}
	return v
}

var port = MustParse("8080", strconv.Atoi)

An accepted exception: using panic/recover internally to unwind deep recursion, as encoding/json and text/template do, and converting the panic back to an error before returning to the caller. Recover only your own sentinel panic type, and re-panic anything else.

More on Error Handling & panics

All 37 Error Handling & panics questions