Go语言 如何“捕获”特定错误

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

例如,我使用一个Go标准库函数:

func Dial(network, address string) (*Client, error)

这个函数可能会返回错误,我只关心报告“连接丢失”或“连接拒绝”的错误,然后做一些代码来修复这些错误。
看起来像是:

client, err := rpc.Dial("tcp", ":1234")  
if err == KindOf(ConnectionRefused) {
  // do something
}

更重要的是,如何获得一个特定的标准库函数可能返回的所有错误?

50few1ms

50few1ms1#

在现代Go语言中,最好的通用方法是使用标准库中的errors.Iserrors.As函数。
对于原始问题中的例子,这是非常直接的:

if errors.Is(err, syscall.ECONNREFUSED) {
    // Connection refused error
} else {
    // Some other kind of error
}

但是,这仅适用于正确 Package /创建以使用这些功能的错误。有时您可能需要混合使用errors.Iserrors.As与字符串比较。我做了一个a video,为那些感兴趣的人提供了一些细节。
我的老答案:
没有标准的方法来做到这一点。
最明显的方法是将错误字符串与您期望的字符串进行比较,只有在没有其他方法可用时才应使用该方法:

if err.Error() == "connection lost" { ... }

或者在某些情况下更健壮:

if strings.HasSuffix(err.Error(), ": connection lost") { ... }

但是许多库将返回特定的错误类型,这使得这变得容易得多。
在您的例子中,相关的是net包导出的各种错误类型:AddrError、DNSConfigError、DNSError、Error等。
您可能最关心net.Error,它用于网络错误。你可以这样检查:

if _, ok := err.(net.Error); ok {
    // You know it's a net.Error instance
    if err.Error() == "connection lost" { ... }
}

更重要的是,如何获得一个特定的标准库函数可能返回的所有错误?
要做到这一点,唯一简单的方法是阅读库的源代码。在走极端之前,第一步是简单地阅读godoc,就像net包一样,错误有很好的文档记录。

jdgnovmf

jdgnovmf2#

现在可以使用errors.Is()函数来比较一些标准误差:

client, err := net.Dial("tcp", ":1234")
if errors.Is(err, net.ErrClosed) {
    fmt.Println("connection has been closed.")
}

常见的文件打开场景:

file, err := os.Open("non-existing");
if err != nil {
    if errors.Is(err, fs.ErrNotExist) {
        fmt.Println("file does not exist")
    } else {
        fmt.Println(err)
    }
}

更新

如果你想检查错误类型,你也可以使用errors.As()

client, err := net.Dial("tcp", ":1234")
var errC = net.ErrClosed
if errors.As(err, &errC) {
    fmt.Printf("connection has been closed: %s", errC)
}
client.Close()

更详细的解释可以在Go Blog中找到。

相关问题