Unwrap doesn't return the base error
Wrapping an error with errors.Wrap, unwrapping it with errors.Unwrap returns the whole error and not the base one. Is it intentional?
https://play.golang.org/p/baYpfrrvN35
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.
https://github.com/pkg/errors/blob/master/go113.go
As @davecheney said the behaviour of the Unwrap in the pkg/errors is the same that the standard library:
https://play.golang.org/p/73xe4gnoXKz
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.