Go 1.23 中 errors.Is 的一点小改动

文摘   2024-07-24 18:14   中国香港  

在 Go 1.23 中,errors.Is 增加了 nil 检查,这使得在处理错误时更简洁明了。这是 Go 1.23rc 的 release notes[1]

不过里面并没有对 errors.Is 的修改做太多说明。在 Go 1.23 之前,errors.Is 不会检查正在检查的错误是否为零。当时的代码[2]如下:

func Is(err, target error) bool {
 if target == nil {
  return err == target
 }

 isComparable := reflectlite.TypeOf(target).Comparable()
 return is(err, target, isComparable)
}

因此,要检查函数返回的错误是否是特定错误,就必须使用嵌套的 if 语句,就像这样:

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 语句。这一改进归功于以下代码变更:

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 只检查目标错误(即预定义错误)是否为零。但现在它也会检查实际返回的错误是否为零。因此,我们可以对代码进行如下改进:

err := foo()
if errors.Is(err, errorBar) {
  // handle error Bar
}
if errors.Is(err, errorBar2) {
  // handle error Bar2
}
if err != nil {
  // handle other errors
}

笔者认为这种方法比以前的代码更好。虽然看起来只是一个小改动,但与旧版本相比,它大大提高了可读性,降低了复杂性,避免了不必要的 nil panic。

前面的代码包含嵌套的 if 语句,尽管最初编写时看起来简单明了,但日后阅读时可能会更加混乱和复杂。

参考资料
[1]

go1.23 release notes: https://tip.golang.org/doc/go1.23

[2]

wrap.go: https://github.com/golang/go/blob/go1.22.5/src/errors/wrap.go#L44-L51


Go Official Blog
Golang官方博客的资讯翻译及独家解读
 最新文章