【发布时间】:2022-11-14 21:02:15
【问题描述】:
使用 go 时,有一种模式用于定义错误并以(对我而言)非常特殊的方式处理它们。通常错误声明为ErrorSomethingWentWrong = errors.New("Just an example!")。您可以使用errors.Is(err, ErrorSomethingWentWrong) 来捕获该特定错误。 Is 函数可以通过比较指针来做到这一点。但是为了进行比较,我需要知道使用哪个变量名来定义errorString,这样我就可以使用errors.Is 来捕获它。
例如:
ErrorSomethingWentWrong = errors.New("Just an example!")
func DoSomething() (*Something, error) {
return nil, ErrorSomethingWentWrong
}
我知道字符串 "Just an example!" 返回错误,但我不知道它有变量名 ErrorSomethingWentWrong:
func checkError() {
if errors.Is(err, ErrorSomethingWentWrong){ // how to know this???
//handle error
}
}
当我使用errors.Is(err, ErrorSomethingWentWrong) 时,我可以捕捉到这个错误并处理它。使用调试时,我看不到 errorString 代表 ErrorSomethingWentWrong 变量。但是当我不知道变量名是ErrorSomethingWentWrong 时,我需要对代码进行逆向工程或阅读文档以了解返回的是哪个错误。
那么如何知道使用调试或反射来检索错误变量名呢?
【问题讨论】:
-
Go 值和它可能存储在其中的变量名称没有任何联系。给定一个值,您无法判断哪些变量存储该值,可能有多个、一个或根本没有。
db.ErrorNotFound的值可以存储在名为db.ErrorFound的变量中。再次,没有联系。请查阅您正在使用的 API 或包的文档,文档应该涵盖这些内容。 -
@icza 我同意并理解。但是
errors.Is()如何根据变量名区分错误呢?当没有文档并且使用的库是一个黑盒子时,我应该如何嗅探这个变量名。 -
errors.Is()是一个函数,Go价值观传递给它,而不是变量名。errors.Is(err, db.ErrorNotFound)接收 2 个值,该值存储在err和db.ErrorNotFound变量中。errors.Is()作用于值,而不是变量名。errors.Is()检查存储在err中的值是否是存储在db.ErrorNotFound变量中的值或包装了该值。 -
@icza感谢您的回答,您是对的,它正在比较值。但是这go.dev/play/p/WjFsCaKdHJG 怎么可能呢?两个具有完全相同值的错误,仍然可以区分。是否可以比较指针是否相等?这是辉煌的。但是现在我仍然需要变量名来指向指针。 (对不起,我不是 C 程序员,指针的概念对我来说是新的)
-
是的,
errors.New()故意创建新的、不同的错误值,即使使用相同的文本也是如此。它通过使用指针来实现。
标签: go design-patterns error-handling