There are several error types in the standard library that wrap errors. net/url.Error, for example, 'reports an error and the operation and URL that caused it.' This error type is used (among other places) within the net/http.Client to annotate any errors it gets from its http.RoundTripper transport.
As a result, this test (for example) would not pass:
package main
import (
"fmt"
"net/http"
"testing"
"github.com/pkg/errors"
)
// failingTransport is a http.RoundTripper which always returns an error.
type failingTransport struct {
err error // the error to return
}
func (t failingTransport) RoundTrip(*http.Request) (*http.Response, error) {
return nil, t.err
}
func TestClientErrorsCanBeCaused(t *testing.T) {
rootErr := fmt.Errorf("some root cause")
c := &http.Client{
Transport: &failingTransport{rootErr},
}
_, err := c.Get("bogus")
cause := errors.Cause(err)
if cause != rootErr {
t.Errorf("err cause is %q, want %q", cause, rootErr)
}
}
-> % go test -v ./errwrap_test.go
=== RUN TestClientErrorsCanBeCaused
--- FAIL: TestClientErrorsCanBeCaused (0.00s)
errwrap_test.go:28: err cause is "Get bogus: some root cause", want "some root cause"
FAIL
exit status 1
FAIL command-line-arguments 1.090s
I think that test should pass, though. Otherwise, I need to write my own series of type assertions to unpack the real root cause. The errors package could unpack the standard library types which are clearly wrappers. I think those are these:
All of these may be useful, but I think the most important are the net ones, in my experience.
The implementation seems straightforward, if you're willing to accept the smelliness of a series of special-case type assertions in the Cause function.
There are several error types in the standard library that wrap errors. net/url.Error, for example, 'reports an error and the operation and URL that caused it.' This error type is used (among other places) within the
net/http.Clientto annotate any errors it gets from itshttp.RoundTrippertransport.As a result, this test (for example) would not pass:
I think that test should pass, though. Otherwise, I need to write my own series of type assertions to unpack the real root cause. The errors package could unpack the standard library types which are clearly wrappers. I think those are these:
All of these may be useful, but I think the most important are the
netones, in my experience.The implementation seems straightforward, if you're willing to accept the smelliness of a series of special-case type assertions in the Cause function.