覆盖错误。is()不适用于自定义错误

时间:2020-08-07 17:11:20

标签: go

我正在尝试在Go中创建一个自定义错误,以便可以使用自定义消息创建该错误的新实例,然后处理该特定类型的错误。但是,当我尝试执行此操作时,未执行覆盖的errors.Is()。这是我的代码:

package main

import (
        "fmt"
        "errors"
)

type Error struct {
        Message string
        Code int
}

func (e *Error) Error() string {
        return e.Message
}

func (e Error) Is(target Error) bool {
        // This is never printed - this method never excutes for some reason
        fmt.Println("compared!")
        return e.Code == target.Code
}

var NotFoundError *Error = &Error{Code: 404, Message: "The page was not found"}

func NewError(errorType *Error, message string) error {
        rc := *errorType
        rc.Message = message

        return &rc
}

func FetchImage() error {
        return NewError(NotFoundError, "That image is gone")
}

func main() {
        err := FetchImage()

        // Returns false
        fmt.Println(errors.Is(err, NotFoundError))
}

在这种情况下,对errors.Is()的调用返回false。但是,即使我提供了自己的Is()函数,也根本不会调用该函数。也就是说,不会打印字符串"compared!"

为什么我的Is()函数不能按预期运行?

2 个答案:

答案 0 :(得分:2)

type Error struct {
        Message string
        Code int
}

func (e *Error) Error() string {
        return e.Message
}

func (e *Error) Is(tgt error) bool {
        // This is never printed - this method never excutes for some reason
        fmt.Println("compared!")
        target, ok := tgt.(*Error)
        if !ok{
          return false
        }
        return e.Code == target.Code
}

您的错误结构未正确实现Is方法,参数应为error而不是Error

查看实际情况:

https://play.golang.org/p/vRQndE9ZRuH

答案 1 :(得分:0)

您可以使用此:

package main

import (
        "fmt"
)

type Error struct {
        Message string
        Code int
}

func (e *Error) Error() string {
        return e.Message
}

func (e *Error) Is(target Error) bool {
        // This is now printed
        fmt.Println("compared!")
        return e.Code == target.Code
}

var NotFoundError Error = Error{Code: 404, Message: "The page was not found"}

func NewError(errorType Error, message string) Error {
        rc := errorType
        rc.Message = message

        return rc
}

func FetchImage() Error {
        return NewError(NotFoundError, "That image is gone")
}

func main() {
        err := FetchImage()

        // Now it returns true
        fmt.Println(err.Is(NotFoundError))
}