Don't Panic

Code running in production must avoid panics. Panics are a major source ofcascading failures. If an error occurs, the function must return an error andallow the caller to decide how to handle it.

BadGood
  1. func foo(bar string) {
  2. if len(bar) == 0 {
  3. panic("bar must not be empty")
  4. }
  5. // …
  6. }
  7.  
  8. func main() {
  9. if len(os.Args) != 2 {
  10. fmt.Println("USAGE: foo <bar>")
  11. os.Exit(1)
  12. }
  13. foo(os.Args[1])
  14. }
  1. func foo(bar string) error {
  2. if len(bar) == 0
  3. return errors.New("bar must not be empty")
  4. }
  5. // …
  6. return nil
  7. }
  8.  
  9. func main() {
  10. if len(os.Args) != 2 {
  11. fmt.Println("USAGE: foo <bar>")
  12. os.Exit(1)
  13. }
  14. if err := foo(os.Args[1]); err != nil {
  15. panic(err)
  16. }
  17. }

Panic/recover is not an error handling strategy. A program must panic only whensomething irrecoverable happens such as a nil dereference. An exception to this isprogram initialization: bad things at program startup that should abort theprogram may cause panic.

  1. var _statusTemplate = template.Must(template.New("name").Parse("_statusHTML"))

Even in tests, prefer t.Fatal or t.FailNow over panics to ensure that thetest is marked as failed.

BadGood
  1. // func TestFoo(t testing.T)
  2. f, err := ioutil.TempFile("", "test")
  3. if err != nil {
  4. panic("failed to set up test")
  5. }
  1. // func TestFoo(t testing.T)
  2.  
  3. f, err := ioutil.TempFile("", "test")
  4. if err != nil {
  5. t.Fatal("failed to set up test")
  6. }