【问题标题】:How to `catch` specific errors如何“捕捉”特定错误
【发布时间】:2017-09-22 04:18:57
【问题描述】:

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

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

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

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

此外,如何获取特定标准库函数可能返回的所有错误?

【问题讨论】:

标签: go error-handling


【解决方案1】:

没有标准的方法来做到这一点。

只有在没有其他方法可用时才应使用的最明显方法是将错误字符串与您期望的字符串进行比较:

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

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

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

但是许多库会返回特定的错误类型,这让这变得容易得多。

在您的情况下,net 包导出的各种错误类型相关:AddrErrorDNSConfigErrorDNSErrorError 等。

您可能最关心net.Error,它用于网络错误。所以你可以这样检查:

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

另外,如何获取特定标准库函数可能返回的所有错误?

做到这一点的唯一万无一失的方法是阅读库的源代码。在走到那个极端之前,第一步就是简单地阅读 godoc,就像 net 包的情况一样,错误已经很好地记录了。

【讨论】:

  • 这是我希望存在的语言功能。它的不存在让我很难过:(
  • @alex:自 2017 年以来,情况发生了一些变化。现在 errors.Iserrors.As 方法促进了这一点。
  • 嘿@Flimzy 感谢您让我知道。您能更新您对这篇文章的原始答案吗?如果您可以添加类似 Updated 2021 之类的部分,那就太好了。我认为很多人都会看到这个答案,并且更新它会很棒。谢谢!
  • 这个 err.(net.Error) 语法是什么?
  • @JBaczuk:那是type assertion。如果错误的基础类型是net.Errorok 将评估为真。
【解决方案2】:

您现在可以使用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找到。

【讨论】:

    猜你喜欢
    • 2010-12-06
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2016-06-02
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多