Created
November 22, 2024 15:38
-
-
Save IlyasYOY/8c3334f760b42eda393ffc81504f586c to your computer and use it in GitHub Desktop.
Revisions
-
IlyasYOY created this gist
Nov 22, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,44 @@ package detailederror import "errors" type detailedError struct { err error key string val string } func (d *detailedError) Error() string { return d.err.Error() } func WithDetails(err error, key, value string) error { return &detailedError{ err: err, key: key, val: value, } } func GetDetail(err error, key string) (string, bool) { nextErr := err var derr *detailedError for errors.As(nextErr, &derr) { if derr.key == key { return derr.val, true } nextErr = derr.err } return "", false } func GetDetails(err error) map[string]string { nextErr := err var derr *detailedError details := make(map[string]string, 0) for errors.As(nextErr, &derr) { details[derr.key] = derr.val nextErr = derr.err } return details } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,88 @@ package detailederror_test import ( "errors" "testing" "github.com/IlyasYOY/detailederror" "github.com/google/go-cmp/cmp" ) func TestWithDetails(t *testing.T) { err := errors.New("test") gotErr := detailederror.WithDetails(err, "user", "ilya") if gotErr == nil { t.Errorf("error must not be nil: %v", gotErr) } } func TestGetDetail_Nested(t *testing.T) { err := errors.New("test") key1 := "user1" want1 := "ilya1" detailedErr1 := detailederror.WithDetails(err, key1, want1) key2 := "user2" want2 := "ilya2" detailedErr2 := detailederror.WithDetails(detailedErr1, key2, want2) got2, ok2 := detailederror.GetDetail(detailedErr2, key2) got1, ok1 := detailederror.GetDetail(detailedErr2, key1) if !ok1 { t.Fatalf("value not found by key: %q", key1) } if !ok2 { t.Fatalf("value not found by key: %q", key2) } if got2 != want2 { t.Errorf("value must be equal to %q", want2) } if got1 != want1 { t.Errorf("value must be equal to %q", want1) } } func TestGetDetails_Nested(t *testing.T) { err := errors.New("test") detailedErr1 := detailederror.WithDetails(err, "user1", "ilya1") detailedErr2 := detailederror.WithDetails(detailedErr1, "user2", "ilya2") got := detailederror.GetDetails(detailedErr2) if diff := cmp.Diff(map[string]string{ "user1": "ilya1", "user2": "ilya2", }, got); diff != "" { t.Errorf("(-want +got):\\n%s", diff) } } func TestGetDetail(t *testing.T) { err := errors.New("test") key := "user" want := "ilya" detailedErr := detailederror.WithDetails(err, key, want) got, ok := detailederror.GetDetail(detailedErr, key) if !ok { t.Fatalf("value not found by key: %q", key) } if got != want { t.Errorf("value must be equal to %q", want) } } func TestGetDetail_Absent(t *testing.T) { err := errors.New("test") want := "ilya" detailedErr := detailederror.WithDetails(err, "name", want) _, ok := detailederror.GetDetail(detailedErr, "user") if ok { t.Fatalf("value was found") } }