diff --git a/errors.go b/errors.go index 30b5885..00f8df1 100644 --- a/errors.go +++ b/errors.go @@ -147,6 +147,20 @@ func Wrap(cause error, message string) error { } } +// Wrapf returns an error annotating the cause with the format specifier. +// If cause is nil, Wrapf returns nil. +func Wrapf(cause error, format string, args ...interface{}) error { + if cause == nil { + return nil + } + pc, _, _, _ := runtime.Caller(1) + return &e{ + cause: cause, + message: fmt.Sprintf(format, args...), + loc: loc(pc), + } +} + type causer interface { Cause() error } diff --git a/errors_test.go b/errors_test.go index 5eed1d5..c54bec1 100644 --- a/errors_test.go +++ b/errors_test.go @@ -130,6 +130,9 @@ func TestFprint(t *testing.T) { }, { err: Wrap(Wrap(x, "message"), "another message"), want: "github.com/pkg/errors/errors_test.go:131: another message\ngithub.com/pkg/errors/errors_test.go:131: message\ngithub.com/pkg/errors/errors_test.go:106: error\n", + }, { + err: Wrapf(x, "message"), + want: "github.com/pkg/errors/errors_test.go:134: message\ngithub.com/pkg/errors/errors_test.go:106: error\n", }} for i, tt := range tests { @@ -141,3 +144,29 @@ func TestFprint(t *testing.T) { } } } + +func TestWrapfNil(t *testing.T) { + got := Wrapf(nil, "no error") + if got != nil { + t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got) + } +} + +func TestWrapf(t *testing.T) { + tests := []struct { + err error + message string + want string + }{ + {io.EOF, "read error", "read error: EOF"}, + {Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"}, + {Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"}, + } + + for _, tt := range tests { + got := Wrapf(tt.err, tt.message).Error() + if got != tt.want { + t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) + } + } +} diff --git a/example_test.go b/example_test.go index 168cb96..088d009 100644 --- a/example_test.go +++ b/example_test.go @@ -54,3 +54,11 @@ func ExampleFprint() { // github.com/pkg/errors/example_test.go:34: inner // github.com/pkg/errors/example_test.go:33: error } + +func ExampleWrapf() { + cause := errors.New("whoops") + err := errors.Wrapf(cause, "oh noes #%d", 2) + fmt.Println(err) + + // Output: oh noes #2: whoops +}