摘要
在 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 函数缺乏空值检查,这导致了诸多错误和不便,对此我感到相当不满。幸运的是,在 Go 1.23 版本中,errors.is 得到了改进。尽管一些 Go 开发者对此持有不同观点,但这一增强无疑将极大地促进我们编写更清晰、更易于维护的代码,同时提升代码的可读性,并降低其复杂性。