正确捕获 Go errors

92 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情

Go 错误处理

众所周知,Go的处理错误的方式应该是这样:

result,err := myMethod()
if err != nil {
    // do something
}

现在在 Go 中处理错误的只能使用这种明确而稳健的错误处理方式但是。但是如果有太多的业务都需要判断错误,就会看到到处都在error 判断。

像之前面向对象的语言 Java 或 C# ,经常都是使用 try...catch... 模式进行捕获异常。在Go 中没有异常也没有 try catch 。但有两种解决方案:

  • 重写代码以首先检查文件是否存在(您可以使用 os.Stat() ),如果不存在,则创建它——这在这种情况下可能更可取。
  • 利用errors.Is()——如果没有变通方法可以使用(见下文)。

errors.Is()

Go 的错误包有一个函数errors.Is(),它使您能够针对目标测试某个错误,如下所示:

func main(){
    if _,err := os.Open(filePath);err!=nil {
        if errors.Is(err, fs.ErrNotExist){
          // ---
        }else{
         // ---
        }
    }
}

通过这种方式,我们能够捕获 os.Open() 返回的可能错误的特定情况,即“文件不存在”。但是如果使用这种方法就需要找到正确的错误来测试不可能将所有可能的错误拿来进行判断。

在 Go 中,可以测试一些自己定义的错误,也可以测试通用系统错误,例如包 io/fs 中定义的错误:

var (
    ErrInvalid    = errInvalid()    // "invalid argument"
    ErrPermission = errPermission() // "permission denied"
)

这些预定义的错误变量有用的另一种情况是 sql 包,因为即使“找不到行”也是 Go 中的错误:

var errMsg = errors.New("sql: no rows in sql")

z这是关于 sql 包会产生的错误,我们也是可以使用。以上代码说明在无法解决错误并希望专门对其进行测试,因为您想捕获“无行”,但仍然让软件因连接错误等原因而失败! 详细的使用方式:

err:=db.QueryRowContext(ctx,sqlStr)
switch{
    case err == sql.ErrNoRows:
    ...
    case err != nil:
    ...
}

最后,还有另一个函数,errors.As(),其使用方法其实和 errors.Is 类似

if _,err := os.Open(filePath);err!=nil {
 if errors.As(err, &pathError) {
   } 
}