diff --git a/errwrap.go b/errwrap.go index a733bef..44e368e 100644 --- a/errwrap.go +++ b/errwrap.go @@ -44,6 +44,8 @@ func Wrap(outer, inner error) error { // // format is the format of the error message. The string '{{err}}' will // be replaced with the original error message. +// +// Deprecated: Use fmt.Errorf() func Wrapf(format string, err error) error { outerMsg := "" if err != nil { @@ -148,6 +150,9 @@ func Walk(err error, cb WalkFunc) { for _, err := range e.WrappedErrors() { Walk(err, cb) } + case interface{ Unwrap() error }: + cb(err) + Walk(e.Unwrap(), cb) default: cb(err) } @@ -167,3 +172,7 @@ func (w *wrappedError) Error() string { func (w *wrappedError) WrappedErrors() []error { return []error{w.Outer, w.Inner} } + +func (w *wrappedError) Unwrap() error { + return w.Inner +} diff --git a/errwrap_test.go b/errwrap_test.go index 5ae5f8e..8c16a56 100644 --- a/errwrap_test.go +++ b/errwrap_test.go @@ -1,6 +1,7 @@ package errwrap import ( + "errors" "fmt" "testing" ) @@ -41,6 +42,16 @@ func TestGetAll(t *testing.T) { "foo", 1, }, + { + fmt.Errorf("foo: %w", fmt.Errorf("bar")), + "foo: bar", + 1, + }, + { + fmt.Errorf("foo: %w", fmt.Errorf("bar")), + "bar", + 1, + }, } for i, tc := range cases { @@ -83,6 +94,11 @@ func TestGetAllType(t *testing.T) { Wrapf("", nil), 0, }, + { + fmt.Errorf("one: %w", fmt.Errorf("two: %w", fmt.Errorf("three"))), + fmt.Errorf("%w", errors.New("")), + 2, + }, } for i, tc := range cases { @@ -92,3 +108,12 @@ func TestGetAllType(t *testing.T) { } } } + +func TestWrappedError_IsCompatibleWithErrorsUnwrap(t *testing.T) { + inner := errors.New("inner error") + err := Wrap(errors.New("outer"), inner) + actual := errors.Unwrap(err) + if actual != inner { + t.Fatal("wrappedError did not unwrap to inner") + } +}