我正在包装错误(以添加上下文),然后区分两个错误。这是我目前用于测试的场景。 (函数是否正确识别错误?)我的问题是如何减少冗长。
我有两个函数会产生不同的错误:
func a() error {
return errors.New("a")
}
func b() error {
return errors.New("b")
}
它们都被传播错误的第三个函数调用。
func doStuff() error {
err := a()
if err != nil {
return WrapA{err}
}
err = b()
if err != nil {
return WrapB{err}
}
return nil
}
在我的 main 函数中,我区分了这两种错误。
func main() {
fmt.Println("Hello, playground")
err := doStuff()
switch err.(type) {
case WrapA:
fmt.Println("error from doing a")
case WrapB:
fmt.Println("error from doing b")
case nil:
fmt.Println("nil")
default:
fmt.Println("unknown")
}
}
到目前为止,还不错。不幸的是,要实现 WrapA
和 WrapB
,我需要大量代码:
type WrapA struct {
wrappedError error
}
func (e WrapA) Error() string {
return e.wrappedError.Error()
}
func (e WrapA) Unwrap() error {
return e.wrappedError
}
type WrapB struct {
wrappedError error
}
func (e WrapB) Error() string {
return e.wrappedError.Error()
}
func (e WrapB) Unwrap() error {
return e.wrappedError
}
在其他语言中,我会创建一个单一的 Wrap
结构并让 WrapA
和 WrapB
继承自 Wrap
.但我看不到在 Go 中执行此操作的方法。
关于如何减少困惑有什么想法吗?
去 Playground https://play.golang.org/p/ApzHC_miNyV
编辑:
看到jub0bs的回答后,我想澄清一下:
a()
和 b()
都是我无法控制的回调。他们可能会返回各种错误。这就是我包装它们的原因。
最佳答案
如果我对问题的理解正确,你确实可以简化事情:
a
和 b
定义为包级 error
变量,以简化操作并提高性能。WrapA
和 WrapB
错误类型。相反,您可以简单地使用 the %w
verb in conjunction with fmt.Errorf
产生一个新的错误值来包装较低级别的错误。errors.Is
在无标记的 switch
中检查 doStuff
函数返回的更高级别错误的原因。( Playground )
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")
}
}
https://stackoverflow.com/questions/69121476/