| What is not covered here, and what I'm still searching for a good pattern for, is being able to return different errors depending on the type of failure. Suppose you have a function that fetches a model from your database. It can return an error if the given user doesn't have permission to fetch this model, or it can return an error if your db connection barfs for some reason. The calling function needs to be able to differentiate between the two errors. Most of what I've read on the subject makes it seem like people prefer to only ever check if err != nil. The two options I've seen in the wild are: 1. Create a constant for a given error, like: var ErrFetchForbidden = errors.New("FETCH_FORBIDDEN")
Then the calling function can do: if err == ErrFetchForbidden {
return 403
} else if err == ErrFetchNotFound {
return 404
} else {
return 500
}
2. Create a custom type for your error like so: type ErrFetchForbidden string
this has the benefit that the errorer can put more specific info into the error besides the Error() string. var err ErrFetchForbidden = "error retrieving the user object"
return err
and then the caller can switch on type switch v := err.(type) {
case ErrFetchForbidden:
return 403
case ErrFetchNotFound:
return 404
default:
return 500
}
We've gone with option 2 for now, (wrapping them with the pkg/errors package) because it seems simpler. Anyone else have good patterns for handling this? |
Create a custom error type, for example DB Error:
Now you can provide functions like IsTemporary(err).Otherwise, you can use 2# with a twist, instead of matching on a type, you can do:
or even: