Go 中的惯用过滤错误

Idiomatically filtering errors in Go

Go 中的 error 类型非常广泛,实际包含的类型可能因平台和版本而异。通过错误的字符串值 error.Error()?

来过滤我们期望的错误是否惯用

例如:

_, err := conn.Write(b)
if err != nil {
    if !strings.Contains(err.Error(), "peer reset") {
        log.Print(err)
    }
    return
}

有更好的方法吗?

我不确定我在说什么你不知道,但我已经看到了一些处理它的方法:与导出并出现在 godoc 中的已知实例进行比较,比如 io.EOFos.ErrNotExist;当文档承诺某种类型的错误时使用类型断言或开关,例如 *os.PathError*os.LinkError;或放弃并查看消息。第一个应该足够清楚,你已经在你的问题中完成了第三个;检查类型可能如下所示:

if pathErr, ok := err.(*os.PathError); ok {
    log.Fatal("Bad path " + pathErr.Path + ", giving up")
} else if err != nil {
    return err
}

我认为这种情况很少见,但如果您涉及多个潜在类型,您可以想象使用 type switch:

switch err.(type) {
case *os.PathError, *os.LinkError:
    log.Fatal("oof")
case nil:
    // nothing; prevents default
default:
    log.Fatal("huh")
}

(这里错误和行为的选择有点傻——我只是想用语法建立一个模板。)

您在问题中提到的困难部分:可能不清楚您对将返回哪些错误有什么保证。我知道,例如,净错误的 1.5 release notes say that they're standardizing more on net.OpError 比以前多了,但这就是我所知道的。如果有您认为不清楚的重要案例,可能需要深入研究您正在调用的包的源代码,或者向人们提问。

errors.Iserrors.As 添加到较新版本的 Go 现在可以解决这个问题。