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
e
can wrap another errorw
by providing anUnwrap
method that returnsw
.
Bothe
andw
are available to programs, allowinge
to provide additional context tow
or to reinterpret it while still allowing programs to make decisions based onw
.To support wrapping,
fmt.Errorf
now has a%w
verb for creating wrapped errors, and three new functions in theerrors
package (errors.Unwrap
,errors.Is
anderrors.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.Is
instead.
Example:if err == io.ErrUnexpectedEOF
becomes
if errors.Is(err, io.ErrUnexpectedEOF)
- Checks of the form if
err != nil
need not be changed.- Comparisons to
io.EOF
need not be changed, becauseio.EOF
should never be wrapped.If you check for an error type using a type assertion or type switch, use
errors.As
instead. Example:if e, ok := err.(*os.PathError); ok
becomes
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
.