在Go语言中,习惯性地过滤错误。

huangapple go评论95阅读模式
英文:

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
}

有没有更好的方法来处理这个问题?

英文:

The error type in Go is quite broad, and the actual type contained can vary by platform as well as between versions. Is it idiomatic to filter errors that we expect by the error's string value, error.Error()?

For example:

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

Is there a better way to do this?

答案1

得分: 3

我不确定我是否说了你不知道的内容,但我见过几种处理方法:与导出并出现在godoc中的已知实例进行比较,例如io.EOFos.ErrNotExist;当文档承诺某种特定类型的错误时,使用类型断言或switch,例如*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版本的发布说明说他们在网络错误方面更多地使用net.OpError,但这就是我所知道的。如果你认为有重要的情况不清楚,可以深入研究你调用的包的源代码,或者向人们提问。

英文:

I'm not sure I'm saying anything you don't know, but I've seen a few ways to handle it: compare to known instances when they are exported and appear in the godoc, like io.EOF or os.ErrNotExist; using type assertions or switches when the docs promise an error of a certain type, like *os.PathError or *os.LinkError; or giving up and looking at messages. The first should be clear enough and you've done the third in your question; checking for type could look like:

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

I think this would be rare, but if you had several potential types involved, you could conceivably use a type switch:

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

(The choice of error and behavior here is a bit silly--I'm just trying to put up a template with the syntax.)

The hard part you allude to in your question: it may not be clear what guarantees you have about what errors will be returned. I know that, for example, the 1.5 release notes say that they're standardizing more on net.OpError for net errors than before, but that's all I know. Spelunking in the source of the package you're calling, or asking people questions, may be in order if there are important cases you think are unclear.

答案2

得分: 0

errors.Iserrors.As是Go语言的较新版本中新增的功能,现在可以解决这个问题。

英文:

errors.Is and errors.As added in more recent versions of Go would now address this problem.

huangapple
  • 本文由 发表于 2015年8月2日 12:54:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/31768689.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定