# 错误处理

# 要点

  • Error需要常量,不能是变量
  • Error需要wrap,方便排查问题
  • Error需要用IS判断,不能用=判断
  • Error需要收敛

# Error是常量

第一个问题是io.EOF公共变量-导入io包的任何代码都可能更改的值io.EOF。事实证明,在大多数情况下,这并不是什么大问题,但可能数据被人篡改,引发不必要的问题。

fmt.Println(io.EOF == io.EOF) // true
x := io.EOF
fmt.Println(io.EOF == x)      // true
	
io.EOF = fmt.Errorf("whoops")
fmt.Println(io.EOF == io.EOF) // true
fmt.Println(x == io.EOF)      // false
1
2
3
4
5
6
7

正确的用法,应该如下所示

const eof = Error("eof")

func (r * Reader) Read([] byte) (int, error){ 
        return 0, eof 
} 

func main () { 
        var r Reader 
        _,err: = r.Read([] byte {})
        fmt.Println(err == eof)// true 
}
1
2
3
4
5
6
7
8
9
10
11

# Error需要wrap

GO1.13支持了error wrap。我们可以在错误以下方法,将原始错误进行包装。fmt.Errorf里是%w

err = fmt.Errorf("wrap error %w", err)
1

这里需要提醒一点,go官方的error wrap没有堆栈信息,还是比较坑爹

# Error需要IS

以往我们对错误判断都是=,但是如果使用了wrap,在用=是无法相等的:

selectErr := fmt.Errorf("select info err: %w", gorm.IsNotRecord)
fmt.Println(selectErr == gorm.IsNotRecord) // false
fmt.Println(errors.Is(selectErr, gorm.IsNotRecord)) // true
1
2
3

# Error需要收敛

# Error说明

目前官方error没有支持堆栈,可能使用pkg/errors排查问题更方便。 但ego为了支持官方后续升级,还是决定使用官方error用法。

# 引用文献

上次更新: 2024-01-25 09:16:20