Declaring an error, and comparing it with ‘==‘ (as in err == myPkg.ErrTokenExpired) is no longer the best practice with Go 1.13 (Q3 2019)
The release notes mentions:
Go 1.13 contains support for error wrapping, as first proposed in the Error Values proposal and discussed on the associated issue.
An error
ecan wrap another errorwby providing anUnwrapmethod that returnsw.
Botheandware available to programs, allowingeto provide additional context towor to reinterpret it while still allowing programs to make decisions based onw.To support wrapping,
fmt.Errorfnow has a%wverb for creating wrapped errors, and three new functions in theerrorspackage (errors.Unwrap,errors.Isanderrors.As) simplify unwrapping and inspecting wrapped errors.
So the Error Value FAQ explains:
You need to be prepared that errors you get may be wrapped.
If you currently compare errors using
==, useerrors.Isinstead.
Example:if err == io.ErrUnexpectedEOFbecomes
if errors.Is(err, io.ErrUnexpectedEOF)
- Checks of the form if
err != nilneed not be changed.- Comparisons to
io.EOFneed not be changed, becauseio.EOFshould never be wrapped.If you check for an error type using a type assertion or type switch, use
errors.Asinstead. Example:if e, ok := err.(*os.PathError); okbecomes
var e *os.PathError if errors.As(err, &e)Also use this pattern to check whether an error implements an interface. (This is one of those rare cases when a pointer to an interface is appropriate.)
Rewrite a type switch as a sequence of
if-elses.