不会还有人不知道Go的错误机制吧!

57 阅读1分钟

Go的错误机制

  • 没有异常机制
  • error类型实现了error接口
  • 可以通过errors.New来快速创建错误实例,errors.New("n must be in the range [0, 10]")

image.png

如何使用错误机制?

func GetFibonacci(n int) ([]int, error) {
   //错误处理
   if n < 2 || n > 100 {
      return nil, errors.New("n should be  in [2, 100]")
   }
   fibList := []int{1, 1}
   for i := 2; i < n; i++ {
      //加入到集合当中
      fibList = append(fibList, fibList[i-1]+fibList[i-2])
   }
   return fibList, nil
}

func TestGetFibonacci(t *testing.T) {
   //判断是否出错
   if v, err := GetFibonacci(-10); err != nil {
      t.Error(err)
   } else {
      t.Log(v)
   }
}

image.png

优雅使用错误机制

//预先定义错误,方便后续对错误进行判断
var LessThanTwoError = errors.New("n should be not less than 2")
var LargerThanHundredError = errors.New("n should be not larger than 100")

func GetFibonacci(n int) ([]int, error) {
   //错误处理
   if n < 2 {
      return nil, LessThanTwoError
   }
   if n > 100 {
      return nil, LargerThanHundredError
   }
   fibList := []int{1, 1}
   for i := 2; i < n; i++ {
      //加入到集合当中
      fibList = append(fibList, fibList[i-1]+fibList[i-2])
   }
   return fibList, nil
}

func TestGetFibonacci(t *testing.T) {
   //判断是否出错
   if v, err := GetFibonacci(-10); err != nil {
      if err == LessThanTwoError {
         fmt.Println("n < 2")
      } else if err == LargerThanHundredError {
         fmt.Println("n > 100")
      } else {
         fmt.Println("Unkown Error")
      }
   } else {
      t.Log(v)
   }
}

image.png

panic与os.Exit

panic

  • panic用于不可恢复的错误
  • panic退出前会执行defer指定的内容
func TestPainicVsExit(t *testing.T) {
   defer func() {
      fmt.Println("Finally")
   }()
   fmt.Println("Start")
   panic(errors.New("Something wrong!"))
   //os.Exit(-1)
   fmt.Println("End")
}

image.png

os.Exit

  • os.Exit退出时不会调用defer指定的函数
  • os.Exit退出时不输出当前调用栈信息
func TestPainicVsExit(t *testing.T) {
   defer func() {
      fmt.Println("Finally")
   }()
   fmt.Println("Start")
   //panic(errors.New("Something wrong!"))
   os.Exit(-1)
   fmt.Println("End")
}

image.png

recover(不推荐使用)

  • 形成僵尸服务进程,导致health check失效
  • “Let it Crash!”往往是我们恢复不确定性错误的最好方法
func TestPainicVsExit(t *testing.T) {
   //错误恢复
   defer func() {
      if err := recover(); err != nil {
         fmt.Println("recovered from", err)
      }
   }()
   fmt.Println("Start")
   panic(errors.New("Something wrong!"))
   //os.Exit(-1)
   fmt.Println("End")
}

image.png

本文章参考来自Go语言从入门到实战