Open yaziine opened 4 years ago
errors.Unwraps only unwraps errors wrapper with errors.Wrap, not fmt.Errorf
Not sure to understand you here. Do you mean that errors.Unwraps only unwraps errors wrapped with fmt.Errorf instead?
Unwrap is just a wrapper around the stdlib errors package's Unwrap.
As @davecheney said the behaviour of the Unwrap
in the pkg/errors
is the same that the standard library:
Oh, this might be the source of the confusion: Wrap(…)
returns a &withStack{ &withMessage{ … } }
and so when one calls Unwrap()
on it, one gets the &withMessage{ … }
rather than the original message that was put into Wrap(…)
, which makes it appear like it is not unwrapping, unless you’re printing stack traces: https://play.golang.org/p/x0JN-W_FStu
This ends up being misleading because one would naturally expect err2 := errors.Unwrap(errors.Wrap(err1))
would result in err2 == err1
but it does not, because internally errors.Wrap
is actually double wrapping. No one noticed when using Cause(…)
because it kept unwrapping until it got to a non-Causer, but errors.Unwrap
only unwraps a single layer. :confused:
should use errors.Cause(err) https://play.golang.org/p/L-uJU07lCAu
errors.Cause
will repeatedly unwrap all of the pkg/errors
wrappings. So we get:
err := stdErrors.New("thing")
err2 := errors.WithMessage(err, "inner wrap")
err3 := errors.Wrap(err, "outer wrap")
cause := errors.Cause(err3)
unwrap := errors.Unwrap(err3)
// (cause == err) == true
// (unwrap != err3 && unwrap != err2 && unwrap != err) == true
There is no way in this scenario to retrieve err2
from err3
, and that’s not ideal.
Wrapping an error with
errors.Wrap
, unwrapping it witherrors.Unwrap
returns the whole error and not the base one. Is it intentional?https://play.golang.org/p/baYpfrrvN35