去检查自定义错误的类型

mco*_*lin 24 error-handling go

我很难在Go中使用自定义错误类型.我阅读了关于错误的博客文章

所以我尝试了这个:

在我的模型中.我定义了一个自定义错误:

type ModelMissingError struct {
    msg string // description of error
}

func (e *ModelMissingError) Error() string { return e.msg }
Run Code Online (Sandbox Code Playgroud)

在我的一个方法中,我抛出一个这样的自定义错误:

...
return Model{}, &ModelMissingError{"no model found for id"}
...
Run Code Online (Sandbox Code Playgroud)

在该方法的调用者中,我想检查为其类型返回的错误,如果它实际上是a,则采取措施ModelMissingError.

我怎样才能做到这一点?

我试过这个:

if err == model.ModelMissingError 
Run Code Online (Sandbox Code Playgroud)

结果是 *type model.ModelMissingError is not an expression*

显然我错过了一些东西.

bla*_*een 55

要检查错误的类型,请使用errors.As

\n
\n

As查找 err 链中与目标匹配的第一个错误 [...] \xe2\x80\x8b 如果错误的具体值可分配给目标指向的值,则错误与目标匹配

\n
\n

当然,类型同一性是可分配性的一个条件。

\n

所以它看起来像:

\n
target := &model.ModelMissingError{} \nif errors.As(err, &target) {\n    fmt.Println(target) // no model found for id\n}\n
Run Code Online (Sandbox Code Playgroud)\n

注意&上面例子中的两种用法。这是因为:

\n
\n

As如果 target 不是指向实现错误的类型或任何接口类型的非零指针,则会发生恐慌。

\n
\n

在您的情况下,您在指针接收器上Error() string声明了方法,因此要满足的“指向实现接口的类型的指针”是。所以你需要解决两次。errorAs**ModelMissingError

\n
\n

另一种方法errors.Is检查是否相等。

\n
\n

如果错误等于目标或者实现 Is(error) bool 方法使得 Is(target) 返回 true,则认为错误与目标匹配。

\n
\n

这在例如固定错误值的情况下很有用,例如声明为标准库varconst类似标准库的错误io.EOF。举个例子:

\n
var ErrModelMissing = errors.New("no model found for id")\n\nfunc foo() {\n    err := bar()\n    if errors.Is(err, ErrModelMissing) {\n        fmt.Println(err) // no model found for id\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

考虑一下 Go 1.13 的用处errors.As在于errors.Is错误展开。如果您检查任意长调用堆栈顶部的错误,您必须记住,原始错误可能会在冒泡时被包裹到其他错误中。那么直接检查相等性或类型可分配性是不够的。

\n
    err1 := fmt.Errorf("wrapped: %w", &ModelMissingError{})\n    target := &ModelMissingError{}\n    fmt.Println(errors.As(err1, &target)) // true\n    \n    err2 := fmt.Errorf("wrapped: %w", FixedError)\n    fmt.Println(errors.Is(err2, FixedError)) // true\n    fmt.Println(err2 == FixedError) // false\n
Run Code Online (Sandbox Code Playgroud)\n

此外,该软件包与和github.com/pkg/errors兼容:errors.Aserrors.Is

\n
// import pkgerr "github.com/pkg/errors"\n\nerr3 := pkgerr.Wrap(pkgerr.Wrap(&ModelMissingError{}, "wrapped 1"), "wrapped 2")\nfmt.Println(errors.As(err3, &target)) // true\n
Run Code Online (Sandbox Code Playgroud)\n

游乐场: https: //play.golang.org/p/FEzggdBLCqq

\n
\n

当然,如果您确定错误没有被包装,那么一个好的旧类型断言也可以正常工作:

\n
if myerr, ok := err.(*model.ModelMissingError); ok {\n    // handle myerr\n}\n
Run Code Online (Sandbox Code Playgroud)\n


mco*_*lin 44

啊,我想我明白了.我是个笨蛋.阅读博客文章进一步暴露了一点像这样:

serr, ok := err.(*model.ModelMissingError)
Run Code Online (Sandbox Code Playgroud)

这是逗号确定的成语,显然我需要重新做我的go lang巡演

  • 你好,来自未来!这是游览相关部分的链接,实际上解释了这里发生的事情。最好(a)将其与答案链接起来,并(b)直接在答案中引用解释。https://tour.golang.org/methods/15 (10认同)

Mar*_*rez 17

现在使用 Go 1.13,我们可以使用errors包中的以下内容:

if errors.Is(err, model.ModelMissingError) {...}
Run Code Online (Sandbox Code Playgroud)

见博文:https : //blog.golang.org/go1.13-errors

  • error.Is() 查看错误的值。由于OP正在寻找错误的类型,他们会想要使用errors.As() (11认同)

mil*_*onb 14

我已经使用switch语句进行错误断言,如下所示:

 err := FuncModelMissingError()

 switch t := err.(type) {
 default:
     fmt.Println("not a model missing error")
 case *ModelMissingError:
     fmt.Println("ModelMissingError", t)
}
Run Code Online (Sandbox Code Playgroud)

我希望这能够帮到你.


sur*_*oni 7

如果您要跨类型验证:

switch err := errorFromFunction(); err.(type) {
    case nil:
        fmt.Println("No Error Function Executed Successfully")
    case *ErrorType1:
        fmt.Println("Type1 Error: ", err)
    case *ErrorType2:
        fmt.Println("Type2 Error", err)
}
Run Code Online (Sandbox Code Playgroud)

如果您知道错误并想要验证:

err, ok := err.(*ErrorType1)
Run Code Online (Sandbox Code Playgroud)


zan*_*ngw 6

简称

  • 哨兵错误 - 匹配errors.Is
  • 结构化错误 - 匹配errors.As

细节