From edda23923b43acad6863ed08d8f49206e165d4c7 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Sun, 2 Oct 2022 21:51:02 +0200 Subject: [PATCH] feat: adding ErrorsAs --- CHANGELOG.md | 6 ++++++ README.md | 24 ++++++++++++++++++++++++ errors.go | 8 ++++++++ errors_test.go | 24 ++++++++++++++++++++++++ 4 files changed, 62 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bcd10f3..0ec57ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ @samber: I sometimes forget to update this file. Ping me on [Twitter](https://twitter.com/samuelberthe) or open an issue in case of error. We need to keep a clear changelog for easier lib upgrade. +## 1.29.0 (2022-10-02) + +Adding: + +- lo.ErrorAs + ## 1.28.0 (2022-09-05) Adding: diff --git a/README.md b/README.md index 7fec142e..cf06cee9 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,7 @@ Error handling: - [TryCatch](#trycatch) - [TryWithErrorValue](#trywitherrorvalue) - [TryCatchWithErrorValue](#trycatchwitherrorvalue) +- [ErrorsAs](#errorsas) Constraints: @@ -2071,6 +2072,29 @@ ok := lo.TryCatchWithErrorValue(func() error { // caught == true ``` +### ErrorsAs + +A shortcut for: + +```go +err := doSomething() + +var rateLimitErr *RateLimitError +if ok := errors.As(err, &rateLimitErr); ok { + // retry later +} +``` + +1 line `lo` helper: + +```go +err := doSomething() + +if rateLimitErr, ok := lo.ErrorsAs[*RateLimitError](err); ok { + // retry later +} +``` + ## 🛩 Benchmark We executed a simple benchmark with the a dead-simple `lo.Map` loop: diff --git a/errors.go b/errors.go index e9f9c8e6..6427db18 100644 --- a/errors.go +++ b/errors.go @@ -1,6 +1,7 @@ package lo import ( + "errors" "fmt" "reflect" ) @@ -199,3 +200,10 @@ func TryCatchWithErrorValue(callback func() error, catch func(any)) { catch(err) } } + +// ErrorsAs is a shortcut for errors.As(err, &&T). +func ErrorsAs[T error](err error) (T, bool) { + var t T + ok := errors.As(err, &t) + return t, ok +} diff --git a/errors_test.go b/errors_test.go index df576108..976efe74 100644 --- a/errors_test.go +++ b/errors_test.go @@ -361,3 +361,27 @@ func TestTryCatchWithErrorValue(t *testing.T) { }) is.False(caught) } + +type internalError struct { + foobar string +} + +func (e *internalError) Error() string { + return fmt.Sprintf("internal error") +} + +func TestErrorsAs(t *testing.T) { + is := assert.New(t) + + err, ok := ErrorsAs[*internalError](fmt.Errorf("hello world")) + is.False(ok) + is.Nil(nil, err) + + err, ok = ErrorsAs[*internalError](&internalError{foobar: "foobar"}) + is.True(ok) + is.Equal(&internalError{foobar: "foobar"}, err) + + err, ok = ErrorsAs[*internalError](nil) + is.False(ok) + is.Nil(nil, err) +}