3 回答
TA贡献1811条经验 获得超6个赞
如果我正确地理解了这个问题,你确实可以简化事情:
定义 和 作为包级变量,以便于使用和提高性能。
a
b
error
除非需要以编程方式访问只能在要包装的错误上下文中访问的值,否则很可能不需要声明这些自定义类型和错误类型。相反,您可以简单地将
%w
谓词与fmt 结合使用。Errorf
以生成包装较低级别错误的新错误值。WrapA
WrapB
然后,您可以使用
错误。在
无标记内检查函数返回的更高级别错误的原因。switch
doStuff
(操场)
package main
import (
"errors"
"fmt"
)
var (
a = errors.New("a")
b = errors.New("b")
)
func doStuff() error {
err := a
if err != nil {
return fmt.Errorf("%w", err)
}
err = b
if err != nil {
return fmt.Errorf("%w", err)
}
return nil
}
func main() {
fmt.Println("Hello, playground")
switch err := doStuff(); {
case errors.Is(err, a):
fmt.Println("error from doing a")
case errors.Is(err, b):
fmt.Println("error from doing b")
case err == nil:
fmt.Println("nil")
default:
fmt.Println("unknown")
}
}
TA贡献1909条经验 获得超7个赞
添加一个结构化的错误版本,该版本沿着各种更具体的错误类型组成一个类型;Wrap
package main
import (
"errors"
"fmt"
)
func a() error {
return errors.New("something more specific broke in a")
}
func b() error {
return errors.New("something more specific broke in b")
}
func doStuff() error {
err := a()
if err != nil {
return ErrA{
Wrap: Wrap{err: err},
SpecficProp: "whatever",
}
}
err = b()
if err != nil {
return ErrB{
Wrap: Wrap{err: err},
SpecficProp2: "whatever else",
}
}
return nil
}
func main() {
fmt.Println("Hello, playground")
err := doStuff()
if target := (ErrA{}); errors.As(err, &target) {
fmt.Printf("%v\n", target)
} else if target := (ErrB{}); errors.As(err, &target) {
fmt.Printf("%v\n", target)
} else if err != nil {
fmt.Println("unknown")
} else {
fmt.Println("nil")
}
}
type Wrap struct {
err error
}
func (e Wrap) Error() string {
return e.err.Error()
}
func (e Wrap) Unwrap() error {
return e.err
}
type ErrA struct {
Wrap
SpecficProp interface{}
}
func (e ErrA) Error() string {
return fmt.Sprintf("got error of kind A with %#v, plus %T", e.SpecficProp, e.Unwrap())
}
type ErrB struct {
Wrap
SpecficProp2 interface{}
}
func (e ErrB) Error() string {
return fmt.Sprintf("got error of kind B with %#v, plus %T", e.SpecficProp2, e.Unwrap())
}
- 3 回答
- 0 关注
- 156 浏览
添加回答
举报