From cd0f0abbb8169eea406e2eabea2d4efc8deed126 Mon Sep 17 00:00:00 2001 From: tdakkota Date: Mon, 21 Feb 2022 17:10:38 +0300 Subject: [PATCH] feat: add Cause function --- cause_test.go | 22 ++++++++++++++++++++++ frame.go | 6 +++--- wrap.go | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 cause_test.go diff --git a/cause_test.go b/cause_test.go new file mode 100644 index 0000000..641baf5 --- /dev/null +++ b/cause_test.go @@ -0,0 +1,22 @@ +package errors + +import ( + "fmt" + "reflect" + "testing" +) + +func TestCause(t *testing.T) { + err1 := fmt.Errorf("1") + erra := Wrap(err1, "wrap 2") + errb := Wrap(erra, "wrap3") + + v, ok := Cause(errb) + if !ok { + t.Error("unexpected false") + return + } + if !reflect.DeepEqual(v, erra.(*wrapError).frame) { + t.Errorf("want %+v, got %+v", v, erra.(*wrapError).frame) + } +} diff --git a/frame.go b/frame.go index 75ec0df..e74908c 100644 --- a/frame.go +++ b/frame.go @@ -25,10 +25,10 @@ func Caller(skip int) Frame { return s } -// location reports the file, line, and function of a frame. +// Location reports the file, line, and function of a frame. // // The returned function may be "" even if file and line are not. -func (f Frame) location() (function, file string, line int) { +func (f Frame) Location() (function, file string, line int) { frames := runtime.CallersFrames(f.frames[:]) if _, ok := frames.Next(); !ok { return "", "", 0 @@ -45,7 +45,7 @@ func (f Frame) location() (function, file string, line int) { // after printing any other error detail. func (f Frame) Format(p Printer) { if p.Detail() { - function, file, line := f.location() + function, file, line := f.Location() if function != "" { p.Printf("%s\n ", function) } diff --git a/wrap.go b/wrap.go index 7833483..61f008f 100644 --- a/wrap.go +++ b/wrap.go @@ -41,6 +41,20 @@ func Unwrap(err error) error { return errors.Unwrap(err) } +// Cause returns first recorded Frame. +func Cause(err error) (f Frame, r bool) { + for { + we, ok := err.(*wrapError) + if !ok { + return f, r + } + f = we.frame + r = r || ok + + err = we.err + } +} + type wrapError struct { msg string err error