diff --git a/README.md b/README.md index e6908f9..e8bdd5c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## About -Here's [Go](https://go.dev) package for wrapping, chaining or combining multiple errors for further use with the standard `errors.Is`. You can learn more about working with errors in Go in [this](https://go.dev/blog/go1.13-errors) article. Explore the [example](#example) below for more understanding. +Here's [Go](https://go.dev) package for errors chaining for further examining using the standard `errors.Is`. You can learn more about working with errors in Go in [this](https://go.dev/blog/go1.13-errors) article. Explore [example](#examples) below for more understanding. This package uses [module version numbering](https://go.dev/doc/modules/version-numbers). @@ -16,9 +16,9 @@ With a [correctly configured](https://golang.org/doc/install#testing) Go toolcha go get github.com/electrofocus/errchain ``` -## Example +## Examples -Let's build new error from multiple errors: +Let's build new error from multiple errors and examine it with `errors.Is`: ```go package main diff --git a/errchain.go b/errchain.go index 1bd34a3..a03ac4f 100644 --- a/errchain.go +++ b/errchain.go @@ -46,3 +46,9 @@ func (c chain) Error() string { func (c chain) Is(target error) bool { return errors.Is(c.error, target) || errors.Is(c.next, target) } + +// As finds the first error in chain that matches target, and if one is found, sets +// target to that error value and returns true. Otherwise, it returns false. +func (c chain) As(target any) bool { + return errors.As(c.error, target) || errors.As(c.next, target) +} diff --git a/errchain_test.go b/errchain_test.go index 028a7b3..3f02cf5 100644 --- a/errchain_test.go +++ b/errchain_test.go @@ -1,8 +1,10 @@ package errchain_test import ( + "encoding/json" "errors" "io" + "io/fs" "net/http" "os" "testing" @@ -101,3 +103,43 @@ func TestIs(t *testing.T) { t.Fatalf("unexpected result TRUE for error %s and %s", err, e) } } + +type customErr struct { + text string +} + +func (e customErr) Error() string { + return e.text +} + +func TestAs(t *testing.T) { + + err := errchain.New( + customErr{"first error text"}, + &fs.PathError{Op: "readdir", Path: "home", Err: errors.New("not implemented")}, + &json.SyntaxError{}, + ) + + var ( + err1 customErr + err2 *fs.PathError + err3 *json.SyntaxError + err4 *json.MarshalerError + ) + + if !errors.As(err, &err1) { + t.Fatalf("unexpected result FALSE for error %s and error type %T", err, err1) + } + + if !errors.As(err, &err2) { + t.Fatalf("unexpected result FALSE for error %s and error type %T", err, err2) + } + + if !errors.As(err, &err3) { + t.Fatalf("unexpected result FALSE for error %s and error type %T", err, err3) + } + + if errors.As(err, &err4) { + t.Fatalf("unexpected result TRUE for error %s and error type %T", err, err4) + } +}