From 67f6815b7b43bab241eaf5c4002c778cc87f0379 Mon Sep 17 00:00:00 2001 From: Vlad Lavrishko Date: Fri, 10 Oct 2025 21:58:32 +0300 Subject: [PATCH 1/3] feat(yaerrors): update API add `unwrap last` --- yaerrors/yaerrors.go | 25 +++++++++++++++++++++++-- yaerrors/yaerrors_test.go | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/yaerrors/yaerrors.go b/yaerrors/yaerrors.go index 3bee721..d4e325a 100644 --- a/yaerrors/yaerrors.go +++ b/yaerrors/yaerrors.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net/http" + "strings" "github.com/YaCodeDev/GoYaCodeDevUtils/yalogger" ) @@ -22,8 +23,14 @@ type Error interface { Code() int Error() string Unwrap() error + UnwrapLast() error } +const ( + codeSeparate = " | " + errorSeparate = " -> " +) + // Minimal error implementation for Error interface. type yaError struct { code int @@ -82,7 +89,7 @@ func FromStringWithLog(code int, msg string, log yalogger.Logger) Error { func (e *yaError) Error() string { safetyCheck(&e) - return fmt.Sprintf("%d | %s", e.code, e.traceback) + return fmt.Sprintf("%d%s%s", e.code, codeSeparate, e.traceback) } // Returns the original error that caused this error. @@ -92,12 +99,26 @@ func (e *yaError) Unwrap() error { return e.cause } +// Returns the last error. +func (e *yaError) UnwrapLast() error { + safetyCheck(&e) + + traceback := []byte(e.traceback) + + end := strings.Index(e.traceback, errorSeparate) + if end == -1 { + return errors.New(e.traceback) + } + + return errors.New(string(traceback[:end])) +} + // Wrap adds a message to the error traceback, providing additional context. // It is highly recommended to use this method each time you return the error // to a higher level in the call stack. func (e *yaError) Wrap(msg string) Error { safetyCheck(&e) - e.traceback = fmt.Sprintf("%s -> %s", msg, e.traceback) + e.traceback = fmt.Sprintf("%s%s%s", msg, errorSeparate, e.traceback) return e } diff --git a/yaerrors/yaerrors_test.go b/yaerrors/yaerrors_test.go index e3edcdc..62db387 100644 --- a/yaerrors/yaerrors_test.go +++ b/yaerrors/yaerrors_test.go @@ -1,6 +1,8 @@ package yaerrors_test import ( + "errors" + "fmt" "testing" "github.com/YaCodeDev/GoYaCodeDevUtils/yaerrors" @@ -62,3 +64,24 @@ func TestYaError_Wrap(t *testing.T) { ) } } + +func TestYaErrorUnwrap_Works(t *testing.T) { + err := yaerrors.FromError(404, yaerrors.ErrTeapot, "Not Found") + if !errors.Is(err.Unwrap(), yaerrors.ErrTeapot) { + t.Fatalf( + fmt.Sprintf("Error didn't unwrap as %v", yaerrors.ErrTeapot), + err.Error(), + ) + } +} + +func TestYaErrorUnwrapLast_Works(t *testing.T) { + expected := "Wrapped error" + + err := yaerrors.FromError(404, yaerrors.ErrTeapot, "Not Found").Wrap(expected) + got := err.UnwrapLast() + + if got.Error() != expected { + t.Fatalf("Error didn't unwrap correctly:\n got: %v\n want: %v", got, expected) + } +} From cc02d0b74e95514a71fcfe745f5bd7cf1b275a50 Mon Sep 17 00:00:00 2001 From: Vlad Lavrishko Date: Sat, 11 Oct 2025 23:25:16 +0300 Subject: [PATCH 2/3] chore(yaerrors): fix lint package --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d16bdca..b49de10 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/redis/go-redis/v9 v9.11.0 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.10.0 - golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b golang.org/x/net v0.42.0 golang.org/x/text v0.27.0 gorm.io/driver/sqlite v1.6.0 @@ -54,6 +53,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.40.0 // indirect + golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect golang.org/x/mod v0.26.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.34.0 // indirect From 41b23049626bdba134b193b00b4050f6d5385cf6 Mon Sep 17 00:00:00 2001 From: Vlad Lavrishko Date: Sat, 11 Oct 2025 23:30:34 +0300 Subject: [PATCH 3/3] fix(yaerrors): change API, returns string --- yaerrors/yaerrors.go | 8 ++++---- yaerrors/yaerrors_test.go | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/yaerrors/yaerrors.go b/yaerrors/yaerrors.go index d4e325a..f23fd66 100644 --- a/yaerrors/yaerrors.go +++ b/yaerrors/yaerrors.go @@ -23,7 +23,7 @@ type Error interface { Code() int Error() string Unwrap() error - UnwrapLast() error + UnwrapLastError() string } const ( @@ -100,17 +100,17 @@ func (e *yaError) Unwrap() error { } // Returns the last error. -func (e *yaError) UnwrapLast() error { +func (e *yaError) UnwrapLastError() string { safetyCheck(&e) traceback := []byte(e.traceback) end := strings.Index(e.traceback, errorSeparate) if end == -1 { - return errors.New(e.traceback) + return e.traceback } - return errors.New(string(traceback[:end])) + return string(traceback[:end]) } // Wrap adds a message to the error traceback, providing additional context. diff --git a/yaerrors/yaerrors_test.go b/yaerrors/yaerrors_test.go index 62db387..0fd3a58 100644 --- a/yaerrors/yaerrors_test.go +++ b/yaerrors/yaerrors_test.go @@ -75,13 +75,13 @@ func TestYaErrorUnwrap_Works(t *testing.T) { } } -func TestYaErrorUnwrapLast_Works(t *testing.T) { +func TestYaErrorUnwrapLastError_Works(t *testing.T) { expected := "Wrapped error" err := yaerrors.FromError(404, yaerrors.ErrTeapot, "Not Found").Wrap(expected) - got := err.UnwrapLast() + got := err.UnwrapLastError() - if got.Error() != expected { + if got != expected { t.Fatalf("Error didn't unwrap correctly:\n got: %v\n want: %v", got, expected) } }