From b6ff49baee465e8d654258c387799b92534062b6 Mon Sep 17 00:00:00 2001 From: Theta-Dev Date: Sat, 16 Oct 2021 23:32:06 +0200 Subject: [PATCH 1/2] add ReturnStd --- try/try.go | 30 ++++++++++++------------------ try/try_test.go | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/try/try.go b/try/try.go index 399cd40..a54c6e6 100644 --- a/try/try.go +++ b/try/try.go @@ -179,9 +179,6 @@ func check(args []interface{}) { // return errors there is a Catch function. Note! The handler function f is // called only when err != nil. func Handle(err *Err, f func()) { - // This and Catch are similar but we need to call recover() here because - // how it works with defer. We cannot refactor these to use same function. - // We put real panic objects back and keep only those which are // carrying our errors. We must also call all of the handlers in defer // stack. @@ -208,9 +205,6 @@ func Handle(err *Err, f func()) { // Catch function per non error returning function. See Handle for more // information. func Catch(f func(err Err)) { - // This and Handle are similar but we need to call recover here because how - // it works with defer. We cannot refactor these 2 to use same function. - if r := recover(); r != nil { e, ok := r.(Err) if !ok { @@ -223,9 +217,6 @@ func Catch(f func(err Err)) { // CatchAll is a helper function to catch and write handlers for all errors and // all panics thrown in the current go routine. func CatchAll(errorHandler func(err Err), panicHandler func(v interface{})) { - // This and Handle are similar but we need to call recover here because how - // it works with defer. We cannot refactor these 2 to use same function. - if r := recover(); r != nil { e, ok := r.(Err) if ok { @@ -256,9 +247,6 @@ func CatchTrace(exit int) { // their errors. If you want to annotate errors see Annotate for more // information. func Return(err *Err) { - // This and Handle are similar but we need to call recover here because how - // it works with defer. We cannot refactor these two to use same function. - if r := recover(); r != nil { e, ok := r.(Err) if !ok { @@ -268,13 +256,19 @@ func Return(err *Err) { } } -// Annotate is for annotating an error. It's similar to Returnf but it takes only -// two arguments: a prefix string and a pointer to error. It adds ": " between -// the prefix and the error text automatically. -func Annotate(err *Err, msg string) { - // This and Handle are similar but we need to call recover here because how - // it works with defer. We cannot refactor these two to use same function. +// ReturnStd is like Return, but it returns the Go standard error type. +func ReturnStd(err *error) { + if r := recover(); r != nil { + e, ok := r.(Err) + if !ok { + panic(r) // Not ours, carry on panicking + } + *err = e.Unwrap() + } +} +// Annotate adds additional messages to the error. +func Annotate(err *Err, msg string) { if r := recover(); r != nil { e, ok := r.(Err) if !ok { diff --git a/try/try_test.go b/try/try_test.go index ab7ee0d..ad26fa7 100644 --- a/try/try_test.go +++ b/try/try_test.go @@ -206,6 +206,20 @@ func TestErrCompare(t *testing.T) { } } +func TestReturnStd(t *testing.T) { + tf := func() (err error) { + defer ReturnStd(&err) + String(throw()) + return + } + + err := tf() + + if err.Error() != "this is an ERROR" { + t.Fail() + } +} + func ExampleReturn() { var err Err defer Return(&err) From 34a01c627946349a120fa036956ba81b585c7587 Mon Sep 17 00:00:00 2001 From: Theta-Dev Date: Sun, 17 Oct 2021 10:59:33 +0200 Subject: [PATCH 2/2] Pass through try-compatible errors --- try/try.go | 11 +++++++++-- try/try_test.go | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/try/try.go b/try/try.go index a54c6e6..f24576b 100644 --- a/try/try.go +++ b/try/try.go @@ -47,7 +47,14 @@ type call struct { } // FromErr wraps a standard error into a try-compatible one with extended stack info. -func FromErr(err error) *tryErr { +func FromErr(err error) Err { + // If the error is already try-compatible, return + //nolint:errorlint + cterr, ok := err.(Err) + if ok { + return cterr + } + terr := &tryErr{err: err, callStack: []call{}} pc, _, _, ok := runtime.Caller(0) @@ -82,7 +89,7 @@ func FromErr(err error) *tryErr { } // NewErr creates a new try-compatible error with extended stack info. -func NewErr(msg string) *tryErr { +func NewErr(msg string) Err { return FromErr(errors.New(msg)) } diff --git a/try/try_test.go b/try/try_test.go index ad26fa7..fac96ee 100644 --- a/try/try_test.go +++ b/try/try_test.go @@ -220,6 +220,22 @@ func TestReturnStd(t *testing.T) { } } +func TestCheckTryErr(t *testing.T) { + testErr := NewErr("TestErr") + + tf := func() (err Err) { + defer Return(&err) + Check(testErr) + return + } + + err := tf() + + if err != testErr { + t.Fail() + } +} + func ExampleReturn() { var err Err defer Return(&err)