panic — immediate, unrecoverable (without recover) runtime failure. error — expected, handleable failure returned as a value.
Panic semantics:
recover().recover(), crashes the program with a stack trace.1// Panic for programmer errors2func process(data []int, index int) int {3 if index < 0 || index >= len(data) {4 panic(fmt.Sprintf("index %d out of range", index))5 }6 return data[index]7}89// Recoverable panic10func safeProcess() (result int, err error) {11 defer func() {12 if r := recover(); r != nil {13 err = fmt.Errorf("panic recovered: %v", r)14 }15 }()16 return process([]int{1, 2, 3}, 5) // panics17}
Error semantics:
1// Error for expected failures2func readConfig(path string) (*Config, error) {3 data, err := os.ReadFile(path)4 if err != nil {5 return nil, fmt.Errorf("reading config: %w", err)6 }7 var cfg Config8 if err := json.Unmarshal(data, &cfg); err != nil {9 return nil, fmt.Errorf("parsing config: %w", err)10 }11 return &cfg, nil12}
When to use panic:
init() function failures.When to use error:
Common mistakes:
errors.Is/errors.As for wrapped errors.log.Fatal (calls os.Exit, skips deferred functions).