Go语言 检查fmt.Errorf返回的错误(值或类型)

2lpgd968  于 2023-06-03  发布在  Go
关注(0)|答案(2)|浏览(218)

如果一段代码有自己的错误类型,如

var ErrSomethingWentWrong = errors.New("Something went wrong"

我相信我的代码我可以做到这一点

import github.com/therepo/theproject/thepackage/thatexportstheaboveerror

// code that might return the above error
if err == thatexportstheaboveerror.ErrSomethingWentWrong {
    // handle the particular case
}

如果像本例中那样通过fmt.Errorf返回错误,会发生什么情况?

return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))

值(或类型或其他)检查/Assert应该如何执行?这是唯一的办法吗?

if err != nil {
    if strings.Contains(err.Error(), "unable to authenticate") {
       // handle the particular error
    }
}
thtygnil

thtygnil1#

从Go语言1.13版本开始,the errors package包含了“ Package ”错误的概念。返回“wrapped”错误的例程使用格式中的%w动词调用fmt.Errorf,将内部错误 Package 到外部错误中。然后可以测试外部错误以查看其是否包含特定的内部错误。
在此之前,xerrors提供了相同的一般概念。
这两种方法都要求产生错误值的人使用提供的 Package 接口。您所询问的例程(https://godoc.org/golang.org/x/crypto/ssh的一部分)并没有做到这一点。一些没有 Package 错误的旧代码提供了某种类型的错误测试函数。例如,当os.Open返回一个错误时,os.IsNotExist会告诉您该错误是否是因为文件不存在。
不幸的是,这个特定的包没有这样的测试,所以如果你真的想以编程方式知道这个错误来自这个特定的源,你几乎只能坚持你所建议的(直接字符串检查)。

1zmg4dgp

1zmg4dgp2#

虽然golang.org/x/crypto/ssh包不会出现sentinel错误(wrapped或其他),但ssh.Dial函数提供了使用ssh.NewClientConn进行更多控制的建议。我做了一些简单的研究,看起来这可能是解决方案:

  • 使用net.Dial获得net.Conn
  • 参见https://pkg.go.dev/net#Dial
  • 使用ssh.NewClientConn获取ssh.Conn和控制通道
  • 参见https://pkg.go.dev/golang.org/x/crypto/ssh#NewClientConn
  • 使用ssh.NewClient获得ssh.Client
  • 参见https://pkg.go.dev/golang.org/x/crypto/ssh#NewClient

这允许您将便利功能分解为三个独立的步骤,以便您可以更好地识别这三个点中的哪一个是故障的来源,并显示自定义 Package 的错误,以便您的业务逻辑可以处理这些特定的场景(例如,“失败的端口连接尝试”与“失败的身份验证”)。

相关问题