1 回答
TA贡献1752条经验 获得超4个赞
让我们将这个例子提炼成它的本质。
package customerror
import (
"errors"
)
type CustomError struct {
Aux string
Err error
}
func (cE *CustomError) Error() string { /*...*/ }
func (err *CustomError) Unwrap() error { return err.Err }
func NewFailedToError(aux string, err error) error {
return &CustomError{ Aux: aux, Err: err }
}
var FailedToWriteToFile = NewFailedToError("write to file", nil)
我们现在可以进入要点中的问题:
// Some function just for demonstration.
func WriteToFile() error {
// Something caused some error..
errSome := errors.New("Failed to open file")
// How can I set the `err` value of `FailedToWriteToFile` to `errSome`
// without setting that for all `FailedToWriteToFile` instances (pointer)?
// while still making it of `FailedToWriteToFile` type (errors.Is(errSome, FailedToWriteToFil))?
return FailedToWriteToFile
}
让我们将这个问题重新构建为如何用新消息进行构建。errSome
errors.Is(errSome, FailedToWriteToFil)
我们可以检查错误的文档。是
:
报告错误链中的任何错误是否与目标匹配。
该链由错误本身组成,后跟通过反复调用 Unwrap 获得的错误序列。
如果错误等于目标,或者如果它实现了 Is(错误) bool 的方法,使得 Is(target) 返回 true,则该错误被视为与该目标匹配。
错误类型可能提供 Is 方法,以便将其视为与现有错误等效。例如,如果“我的错误”定义
func (m MyError) Is(目标错误) bool { 返回目标 == fs.错误存在 }
然后 Is(MyError{}, fs.错误存在) 返回真值。有关标准库中的示例,请参阅 syscall.Errno.Is。
这给了我们两条道路。其中一条路径是放在展开链上。如果我们使用 Err 字段指向 ,则自定义错误具有足够的字段,例如FailedToWriteToFile
FailedToWriteToFile
&CustomError{Aux: "Failed to open file", Err: FailedToWriteToFile}
解开包装()是 == 到 。FWIW AUX 可能是类型错误的字段,如果您尝试捕获来自其他源的错误值。只要解开包装()链最终导致。FailedToWriteToFile
FailedToWriteToFile
另一条路径是在 上定义谓词。有很多可能的谓词可供选择。一个简单的问题是,所有 *自定义错误都被视为等效的。这将是:Is
CustomError
func (e *CustomError) Is(target error) bool { _, ok := target.(*CustomError) return ok }
- 1 回答
- 0 关注
- 85 浏览
添加回答
举报