将单个错误传递给errors.Join是否有问题?

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

Is it a problem to pass a single error to errors.Join?

问题

Go 1.20引入了errors.Join函数,可以包装多个错误。调用此函数并只传入一个错误是否会有任何问题?

例如,这篇文章建议不要对可写文件使用defer f.Close()的习惯用法,因为这样会静默忽略Close返回的任何错误。相反,它建议使用命名返回值err来允许Close的返回值传播,除非这样做会覆盖之前的错误:

defer func() {
    cerr := f.Close()
    if err == nil {
        err = cerr
    }
}()

在这种情况下,使用errors.Join似乎更正确:

defer func() {
    cerr := f.Close()
    err = errors.Join(err, cerr)
}()

如果errcerr都不为nil,这将返回两个错误。如果两者都为nil,它将返回nil

然而,如果一个为nil,另一个为非nilerrors.Join将不仅返回非nil错误,还会返回一个包装在errors.joinError中的错误。像这样包装错误是否会引起任何问题?特别是如果调用堆栈中的多个函数都使用这种方法,那么单个错误可能会出现在多个层级的包装中。

英文:

Go 1.20 introduces the errors.Join function that can wrap multiple errors. Are there any issues with calling this function and only passing in a single error?

For example, this article recommends against using the defer f.Close() idiom for writable files, because that would silently ignore any error returned by Close. Instead, it suggests using a named return value err to allow the return value of Close to be be propagated - unless doing so would overwrite an earlier error:

defer func() {
    cerr := f.Close()
    if err == nil {
        err = cerr
    }
}()

It seems more correct to use errors.Join in this scenario:

defer func() {
    cerr := f.Close()
    err = errors.Join(err, cerr)
}()

If both err and cerr are non-nil, this will now return both errors. If both are nil, it will return nil.

However, if one is nil and the other non-nil, errors.Join will not just return the non-nil error but an errors.joinError wrapper around it. Could wrapping an error like this cause any problems? Especially if several functions in the call stack use this approach, so a single error could end up within multiple layers of wrapper?

答案1

得分: 2

如果errors.JoinError只有一个非nil错误,那仍然是一个连接错误,并且errors.Aserrors.Is函数会按预期工作。这在连接错误的嵌套级别无论如何都是正确的。

唯一的潜在问题是如果存在以下代码:

err := someFunc()
if err == io.EOF {
  ...
}

那么这将失败。这段代码必须重写以使用errors.Is

英文:

If errors.JoinError has only one non-nil error, that is still a join-error, and errors.As and errors.Is functions work as expected. This is correct no matter the level of nesting of joined errors.

The only potential problem would be if there is code like:

err:=someFunc()
if err==io.EOF {
  ...
}

then this will fail. This code has to be rewritten to use errors.Is.

huangapple
  • 本文由 发表于 2023年2月14日 02:09:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439684.html
匿名

发表评论

匿名网友

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

确定