diff --git a/README.md b/README.md index 983f440..36ebe0f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,18 @@ # errors -[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fpub-go%2Ferrors.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fpub-go%2Ferrors?ref=badge_shield) + errors with stack, supports multi-cause error format as tree, inspired by [cockroachdb/errors](github.com/cockroachdb/errors) +> 博客:[造一个 Go 语言错误库的轮子](https://youthlin.com/?p=1868) + +[![sync-to-gitee](https://github.com/pub-go/errors/actions/workflows/gitee.yaml/badge.svg)](https://github.com/pub-go/errors/actions/workflows/gitee.yaml) +[![test](https://github.com/pub-go/errors/actions/workflows/test.yaml/badge.svg)](https://github.com/pub-go/errors/actions/workflows/test.yaml) +[![codecov](https://codecov.io/gh/pub-go/errors/graph/badge.svg?token=OfZF3kQlBS)](https://codecov.io/gh/pub-go/errors) +[![Go Report Card](https://goreportcard.com/badge/code.gopub.tech/errors)](https://goreportcard.com/report/code.gopub.tech/errors) +[![Go Reference](https://pkg.go.dev/badge/code.gopub.tech/errors.svg)](https://pkg.go.dev/code.gopub.tech/errors) +[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fpub-go%2Ferrors.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fpub-go%2Ferrors?ref=badge_shield) + Example ```go package main diff --git a/errors.go b/errors.go index 641407d..8612f81 100644 --- a/errors.go +++ b/errors.go @@ -176,9 +176,14 @@ func WithStack(err error) error { } } +// Join 聚合多个错误 func Join(errs ...error) error { + err := join(errs...) + if err == nil { + return nil + } return &withStack{ - error: join(errs...), + error: err, stack: callers(), } } diff --git a/errors_test.go b/errors_test.go index 9df0171..732ecbb 100644 --- a/errors_test.go +++ b/errors_test.go @@ -125,6 +125,12 @@ func TestWithStack(t *testing.T) { } func TestJoin(t *testing.T) { + if err := errors.Join(); err != nil { + t.Errorf("Join() want nil, got: %+v", err) + } + if err := errors.Join(nil); err != nil { + t.Errorf("Join(nil) want nil, got: %+v", err) + } print(t, errors.Join(errFmt, errLeafNew)) } diff --git a/format.go b/format.go index 7d1368d..09b743a 100644 --- a/format.go +++ b/format.go @@ -27,6 +27,11 @@ func Formattable(err error) FormattableError { return &errorFormatter{err} } +// Detail 先将 err 包装为 Formattable 再使用 %+v 格式化为字符串 +func Detail(err error) string { + return fmt.Sprintf("%+v", Formattable(err)) +} + // FormatError 能够识别格式化动词智能打印。 // 当一个错误类型在实现 fmt.Formatter 接口时,可以直接转发给本函数。 // diff --git a/format_test.go b/format_test.go index 7a6de9f..d45fe7a 100644 --- a/format_test.go +++ b/format_test.go @@ -1,6 +1,7 @@ package errors_test import ( + "fmt" "testing" "code.gopub.tech/errors" @@ -16,3 +17,22 @@ func TestFormat(t *testing.T) { err1234 := errors.Join(err12, err34) t.Logf("%+v", err1234) } + +func TestDetail(t *testing.T) { + if s := errors.Detail(nil); s != "" { + t.Errorf("Detail(nil) got %s", s) + } + t.Logf("%s", errors.Detail(errors.New("error"))) + e0 := fmt.Errorf("fmtErr") + err := errors.F(e0) + if e, ok := err.(interface{ Cause() error }); ok { + if e.Cause() != e0 { + t.Errorf("Cause() failed") + } + } + if e, ok := err.(interface{ Unwrap() error }); ok { + if e.Unwrap() != e0 { + t.Errorf("Unwrap() failed") + } + } +}