使用 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
时,我需要对代码进行逆向工程或阅读文档以了解返回了哪个错误。
那么如何知道使用调试或反射来检索错误变量名称呢?
如果我理解正确的话,这就是你的场景:
您收到来自包的错误,并且没有文档为您提供应处理的错误。您正在调试,并看到
errors.errorString
,但不知道是否有可以比较的全局和公共错误值。
不幸的是,这是一个值,调试器无法告诉您这是否是一个全局变量,或者如果是的话是哪一个,因为您没有收到一个变量,只有一个值。
您可以:
如果事实证明您希望处理的特定错误未在全局范围内定义(并且重写包对于您的情况不可行),那么您将无法处理它。如果有人在函数内使用
errors.New
,就会发生这种情况(不好的做法)。那么你也可以尝试这些:
func handleError(err error) {
if err.Error() == "full error string" {}
if strings.Contains(err.Error(), "partial error string") {}
}
但恕我直言,这些都很丑。
TL;DR 这是不可能的,你必须阅读源代码。
需要记住的一件事是,错误可能根本不是变量,而只是值。例如,可以这样做:
func foo() error {
...
if somethingWrong {
return fmt.Errorf("some error")
}
...
另一件事是错误变量可能是私有的(即以小写字母开头)。