其他分享
首页 > 其他分享> > Go语言中常见100问题-#51 Comparing an error value inaccurately

Go语言中常见100问题-#51 Comparing an error value inaccurately

作者:互联网

下面定义了一个全局的error,通常error变量命名以Err开头,后面是错误类型. 哨兵error期望描述的是一个预期的错误,下面以SQL库为例进行说明。

import "errors"

var ErrFoo = errors.New("foo")

设计一个查询数据库的Query方法,该方法返回结果是一个rows切片。在遇到查询结果为空的时候,怎么处理呢?有两个处理方法:

我们关注第二种方法,如果查询的结果为空,返回一个具体的错误。这是一种预期的问题,返回给调用方一个预期的错误用以区分这种情况。然而,在某些情况下,有些错误是难以提前确定的,像网络连接错误。我们并不是不想处理这种错误,而是因为它反映的是不同含义的问题。

在Go标准库中,可以看到不少这种通过哨兵标记错误的例子。

上面是哨兵error想表达的一般原则,返回调用方期望检查的预期错误。因此,有以下准则:

现在分析一个共性的错误。如何比较error? 像下面的代码,可以使用==操作符

err := query()
if err != nil {
        if err == sql.ErrNoRows {
                // ...
        } else {
                // ...
        }
}

然而,在前面的问题Go语言中常见100问题-#49 wrap error中,error可以被包装。如果sql.ErrNoRows被使用fmt.Errorf+%w包装,err==sql.ErrNoRows将会永远不成立。Go1.13版本提供了解决方法。通过errors.As来检测wrap error是否是某种类型,同理,通过errors.Is来检测wrap error的值是否是某个具体的错误。改写后的代码为:

err := query()
if err != nil {
        if errors.Is(err, sql.ErrNoRows) {
                // ...
        } else {
                // ...
        }
}

使用errors.Is替换==比较错误是最佳的做法,因为它也能处理wrap error的情况。

总结,在程序中使用了fmt.Errorf+%w来包装错误,在检查error的时候不能用==,而是用errors.Is, errors.Is会递归的unwrap error检查每层中的error是否是要比较的。

 

标签:返回,err,errors,-#,错误,ErrNoRows,51,value,error
来源: https://www.cnblogs.com/tracydzf/p/16398703.html