习惯性地过滤Go中的错误

习惯性地过滤Go中的错误,go,error-handling,runtime-error,Go,Error Handling,Runtime Error,Go中的错误类型非常广泛,包含的实际类型可能因平台以及版本而异。通过错误的字符串值,error.error(),过滤我们期望的错误,这是惯用做法吗 例如: _, err := conn.Write(b) if err != nil { if !strings.Contains(err.Error(), "peer reset") { log.Print(err) } return } 有更好的方法吗?我不确定我说的是你不知道的,但我看到了一些处理方法:与

Go中的
错误
类型非常广泛,包含的实际类型可能因平台以及版本而异。通过错误的字符串值,
error.error()
,过滤我们期望的错误,这是惯用做法吗

例如:

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

有更好的方法吗?

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

if pathErr, ok := err.(*os.PathError); ok {
    log.Fatal("Bad path " + pathErr.Path + ", giving up")
} else if err != nil {
    return err
}
我认为这是很少见的,但如果你有几个潜在的类型,你可以考虑使用:

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


您在问题中提到的最难的部分是:可能不清楚您对返回的错误有什么保证。我知道,例如,他们说他们比以前更加标准化网络错误,但这就是我所知道的。如果有你认为不清楚的重要案例,探索你所呼叫的软件包的来源或向人们提问可能是正确的。

你已经大致总结了我目前所处的位置。你的例子是净错误;想知道是否值得向golang nuts询问添加
(*net.OpError.Type()
,其中
Type
是一组已知错误值之一(想象一下,
net.ErrConnReset
net.erraddriunse
),或者标准化
OpError.error()
,或者记录一些事实上可靠但没有记录的东西。(如果不是
Type()
,可能是使用POSIX错误代码的
code()
Errno()
。)深入研究
error
的字符串表示法充其量是脆弱的,不是一个好主意。我写了另一个问题,讨论了软件包作者如何产生可供消费者测试的错误。如果您需要测试或处理不使用这些简单方法的错误,那么您已经在该软件包中发现了一个缺陷,并且应该将其报告为一个问题。在处理错误字符串之前,我甚至会先用叉子修复它。您新的“stringly typed”so标记对我来说毫无意义;我建议删除它。
switch err.(type) {
case *os.PathError, *os.LinkError:
    log.Fatal("oof")
case nil:
    // nothing; prevents default
default:
    log.Fatal("huh")
}