poundifdef
poundifdef

Reputation: 19353

Overriding errors.Is() not working with custom errors

I am trying to create a custom error in Go such that I can create new instances of that error with a custom message, and then handle that specific type of error. However, when I try to do this, then my overridden errors.Is() is not being executed. Here is my code:

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))
}

In this case, the call to errors.Is() returns false. However, even though I have supplied my own Is() function, that function is not being called at all. That is, the string "compared!" is never printed.

Why isn't my Is() function working as desired?

Upvotes: 3

Views: 8319

Answers (2)

hutabalian
hutabalian

Reputation: 3484

You can use this:

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))
}

Upvotes: 0

sonus21
sonus21

Reputation: 5388

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
}

Your Error struct does not implement Is method correctly, the parameter should be error not Error.

See in action:

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

Upvotes: 7

Related Questions