摘要
在 Go 1.23 中,errors.Is 函数中添加了一个 nil 检查,可以让处理错误时写出可读性更好的代码。
正文
在 Go 1.23 之前,errors.Is 函数中没有检查 err 参数是否为 nil,当时的代码如下:
1
2
3
4
5
6
7
8
|
func Is(err, target error) bool {
if target == nil {
return err == target
}
isComparable := reflectlite.TypeOf(target).Comparable()
return is(err, target, isComparable)
}
|
因此,要检查函数返回的错误是否为特定的错误,需要像下面这样使用嵌套的 if 语句:
1
2
3
4
5
6
7
8
9
10
|
err := foo()
if err != nil {
if errors.Is(err, errorBar) {
// handle error Bar
}
if errors.Is(err, errorBar2) {
// handle error Bar2
}
// handle other errors
}
|
虽然这段代码看着没有任何问题,当然实际也没有任何问题,只是它看着没有那么的优雅。
在 Go 1.23 中,你可以去掉 if 语句的嵌套,只需要一层代码来处理错误检查。这主要是因为现在的 errors.Is 函数做了一些修改,现在代码如下:
1
2
3
4
5
6
7
8
|
func Is(err, target error) bool {
if err == nil || target == nil {
return err == target
}
isComparable := reflectlite.TypeOf(target).Comparable()
return is(err, target, isComparable)
}
|
以前,errors.Is 只会检查 target 是否等于 nil,现在还会检查 err 是否为 nil。因此,我们可以把错误检查代码改进如下:
1
2
3
4
5
6
7
8
9
10
|
err := foo()
if errors.Is(err, errorBar) {
// handle error Bar
}
if errors.Is(err, errorBar2) {
// handle error Bar2
}
if err != nil {
// handle other errors
}
|
我相信这种方法比之前的代码更好,虽然只做了一点改变,但与旧的代码相比少了一层嵌套,可读性明显提升。
尽管最初编写代码时看起来很简单,但之前的代码中嵌套的 if 语句可能在以后阅读时更加令人困惑和复杂。
另外可读性较好的代码应该优先考虑正常路径,减少不必要的嵌套深度。
结论
当 errors.is 没有进行空值检查时,我在阅读代码时遇到了许多错误和困难,对于 errors.is 中缺乏空值检查我感到非常不满意。
现在 errors.is 在 go 1.23 中已经得到优化,尽管一些 gophers 可能存在哲学分歧,但这个增强将显著有助于编写保持良好路径的代码,提高可读性并减少复杂性。