Go语言学习06-错误处理

Go的错误机制

与其他主要编程语言的差异
  1. 没有异常机制

  2. error类型实现了error接口

  3. 可以通过 errors.New 来快速创建错误实例

    1
    2
    3
    4
    5
    type error interface {
    Error() string
    }

    errors.New("n must be in range [0, 10]")

最佳实践

定义不同的错误变量, 以便于判断错误类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var LessThanTwoError = errors.New("n should be not less than 2")
var LargeThanHundredError = 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, LargeThanHundredError
}
fibList := []int{1, 1}

for i := 2; i < n; i++ {
fibList = append(fibList, fibList[i-2]+fibList[i-1])
}
return fibList, nil
}
func TestGetFibonacci(t *testing.T) {
if v, err := GetFibonacci(-10); err != nil {
if err == LessThanTwoError {
fmt.Println("It is less.")
}
t.Error(err)
} else {
t.Log(v)
}
}
及早失败, 避免嵌套!

panic

  • panic 用于不可恢复的错误
  • panic 退出前会执行 defer 指定的内容

panic vs. os.Exit

  • os.Exit 退出时不会调用 defer 指定的函数
  • os.Exit 退出时不输出当前调用栈信息

recover

1
2
3
4
5
6
// 最常见的"错误恢复"
defer func() {
if err := recover(); err != nil {
Log.Error("recovered panic", err)
}
}()

缺陷:

  • 形成僵尸服务进程, 导致 health check 失效
  • “Let it Crash!” 往往是我们恢复不确定性错误的最好方法