From e6d10916d2fba5e3bdbe6733ca8f6360f8fadb25 Mon Sep 17 00:00:00 2001 From: caixw Date: Sat, 20 Apr 2024 11:49:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20SprintError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/errs/errs.go | 36 ++++++++++++++++++++++++++++++++++++ internal/errs/errs_test.go | 38 ++++++++++++++++++++++++++++++++++++++ web.go | 10 +++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 internal/errs/errs_test.go diff --git a/internal/errs/errs.go b/internal/errs/errs.go index 47e2addc..c33ce7d9 100644 --- a/internal/errs/errs.go +++ b/internal/errs/errs.go @@ -4,3 +4,39 @@ // Package errs 与错误相关的定义 package errs + +import ( + "github.com/issue9/localeutil" + "github.com/issue9/logs/v7" + "golang.org/x/xerrors" +) + +func Sprint(p *localeutil.Printer, err error, detail bool) string { + if err == nil || p == nil { + panic("参数 p 和 err 不能为 nil") + } + + switch t := err.(type) { + case xerrors.Formatter: + b := logs.NewBuffer(detail) + e := t.FormatError(b) + FOR: + for e != nil { + switch tt := e.(type) { + case xerrors.Formatter: + e = tt.FormatError(b) + case localeutil.Stringer: + b.AppendString(tt.LocaleString(p)) + break FOR + default: + b.AppendString(tt.Error()) + break FOR + } + } + return string(b.Bytes()) + case localeutil.Stringer: + return t.LocaleString(p) + default: + return err.Error() + } +} diff --git a/internal/errs/errs_test.go b/internal/errs/errs_test.go new file mode 100644 index 00000000..dfa6809d --- /dev/null +++ b/internal/errs/errs_test.go @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2024 caixw +// +// SPDX-License-Identifier: MIT + +package errs + +import ( + "errors" + "testing" + + "github.com/issue9/assert/v4" + "github.com/issue9/localeutil" + "golang.org/x/text/language" + "golang.org/x/text/message" + "golang.org/x/text/message/catalog" +) + +func TestSprint(t *testing.T) { + a := assert.New(t, false) + + a.Panic(func() { + Sprint(nil, nil, false) + }) + + c := catalog.NewBuilder(catalog.Fallback(language.SimplifiedChinese)) + a.NotError(c.SetString(language.TraditionalChinese, "lang", "tw")) + a.NotError(c.SetString(language.SimplifiedChinese, "lang", "cn")) + p := message.NewPrinter(language.SimplifiedChinese, message.Catalog(c)) + + a.Equal(Sprint(p, errors.New("lang"), false), "lang") + a.Equal(Sprint(p, localeutil.Error("lang"), false), "cn") + + a.Contains(Sprint(p, NewDepthStackError(2, errors.New("lang")), true), "lang") + a.Contains(Sprint(p, NewDepthStackError(2, localeutil.Error("lang")), false), "cn") + + a.Contains(Sprint(p, NewDepthStackError(2, NewDepthStackError(2, errors.New("lang"))), false), "lang") + a.Contains(Sprint(p, NewDepthStackError(2, NewDepthStackError(2, localeutil.Error("lang"))), true), "cn") +} diff --git a/web.go b/web.go index 7ab48a32..cfb53a97 100644 --- a/web.go +++ b/web.go @@ -25,7 +25,7 @@ import ( ) // Version 当前框架的版本 -const Version = "0.92.1" +const Version = "0.93.0" type ( Logger = logs.Logger @@ -96,3 +96,11 @@ func NewLocaleError(format string, v ...any) error { return localeutil.Error(for // // 此方法返回的错误,在 [Context.Error] 和 [Recovery] 中会被识别且按指定的状态码输出。 func NewError(status int, err error) error { return errs.NewError(status, err) } + +// SprintError 将 err 转换为字符串 +// +// p 如果 err 实现了 [LocaleStringer],将采用 p 进行转换; +// detail 是否输出调用堆栈; +func SprintError(p *localeutil.Printer, detail bool, err error) string { + return errs.Sprint(p, err, detail) +}