为了账号安全,请及时绑定邮箱和手机立即绑定

如何创建一个自定义错误,该错误是另一个自定义错误(如继承)的子类型?

如何创建一个自定义错误,该错误是另一个自定义错误(如继承)的子类型?

Go
湖上湖 2022-10-04 15:46:42
对于给定的自定义错误类型:type CustomError struct {    // Err optionally wraps the original error.    Err error `json:"-"`    // Human readable message.    Message string `json:"message" validate:"required,gte=3"`    // StatusCode is a valid HTTP status code, e.g.: 404.    StatusCode int `json:"-"`}其中既实现了,又有接口,也有一个工厂:Error() stringUnwrap() errorfunc NewCustomError(m string, s int, e error) *CustomError {}如何创建另一个“类型”,基于 - 让我们为诸如“未能创建X”之类的错误调用它,默认情况下具有:CustomTypeFailedTo前缀为MessageFailed to状态代码500最重要的是,另一个,例如以某种方式....FailedToCreateSomethingfunc createSomething() error {    return FailedToCreateSomething(errors.New("File is busy"))}errCreateSomething := createSomething()...的类型是 ,也是 和 ?errCreateSomethingFailedToCreateSomethingFailedToCustomError
查看完整描述

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

}

让我们将这个问题重新构建为如何用新消息进行构建。errSomeerrors.Is(errSome, FailedToWriteToFil)

我们可以检查错误的文档。是

报告错误链中的任何错误是否与目标匹配。

该链由错误本身组成,后跟通过反复调用 Unwrap 获得的错误序列。

如果错误等于目标,或者如果它实现了 Is(错误) bool 的方法,使得 Is(target) 返回 true,则该错误被视为与该目标匹配。

错误类型可能提供 Is 方法,以便将其视为与现有错误等效。例如,如果“我的错误”定义

func (m MyError) Is(目标错误) bool { 返回目标 == fs.错误存在 }

然后 Is(MyError{}, fs.错误存在) 返回真值。有关标准库中的示例,请参阅 syscall.Errno.Is。

这给了我们两条道路。其中一条路径是放在展开链上。如果我们使用 Err 字段指向 ,则自定义错误具有足够的字段,例如FailedToWriteToFileFailedToWriteToFile

&CustomError{Aux: "Failed to open file", Err: FailedToWriteToFile}

解开包装()是 == 到 。FWIW AUX 可能是类型错误的字段,如果您尝试捕获来自其他源的错误值。只要解开包装()链最终导致。FailedToWriteToFileFailedToWriteToFile

另一条路径是在 上定义谓词。有很多可能的谓词可供选择。一个简单的问题是,所有 *自定义错误都被视为等效的。这将是:IsCustomError

func (e *CustomError) Is(target error) bool {
  _, ok := target.(*CustomError)  return ok
}


查看完整回答
反对 回复 2022-10-04
  • 1 回答
  • 0 关注
  • 85 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信