不要 Panic

生产级的代码必须避免 panics 。panics 是级联故障的主要源头。如果错误发生,函数应该返回错误并且允许调用者决定如果处理它。

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

Panic/recover 并不是错误处理策略。程序只有在遇到无法处理的情况下才可以 panic ,例如,nil 引用。程序初始化时是一个例外情况:程序启动时遇到需要终止执行的错误可能会 painc 。

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

即使是在测试中,也应优先选择 t.Fatalt.FailNow 而非 panic,以确保测试标记为失败。

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. f, err := ioutil.TempFile("", "test")
  3. if err != nil {
  4. t.Fatal("failed to set up test")
  5. }