【发布时间】:2021-10-14 09:24:32
【问题描述】:
我不确定如何准确地表达这个问题,而且我看到其他人提出了类似的问题,但并没有真正想出答案(这告诉我我问错了问题,但我不知道还有什么办法来解决这个问题)。
我正在尝试学习一些基本的围棋,但我在第一个障碍中遇到了困难。
在我的测试代码中,我正在对不存在的域执行基本的 http GET 以触发 DNS 警告。我发现 err.error() 返回一个字符串,所以为了判断它是否是 DNS 错误,我使用了字符串比较:
resp, err := http.Get(link)
if err != nil {
if strings.Contains(err.Error(), "no such host") == true {
return "no such host"
}
}
这显然是 hacky,所以我做了一些谷歌搜索,看看是否有更好的方法来确定引发了什么样的错误,我找到了以下 SO 答案:
How can I check specific golang net/http error code?
包“errors”有函数As,是解包特定的错误类型,包“net”有一个*DNSError类型。所以:
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) {
...
}
这段代码有效,但我完全不知道这个结论是如何得出的。以下是我试图理解这一点的方法,我想知道我哪里出错了。我(模糊地)了解 .Is() 和 .As() 正在做什么,但我不明白的是如何在没有猜测或先验知识的情况下计算出什么错误“类型”来提供这些功能。
我查看了 client.get() 文档here,上面写着:
任何返回的错误都是 *url.Error 类型。
更多谷歌搜索,我发现我需要将错误转换(?)该类型才能使用它:
urlErr := err.(*url.Error)
*url.Error 包含:
&url.Error{Op:"Get", URL:"http://doesnotexistkjdfhgsdfsdf.com", Err:(*net.OpError)(0xc00021a2d0)}
所以我再看一下url.Error中包含的net.OpError:
netOpError := urlErr.Err.(*net.OpError)
fmt.Printf("Net Op Error contains: %#v\n", netOpError)
---
Net Op Error contains: &net.OpError{Op:"dial", Net:"tcp", Source:net.Addr(nil), Addr:net.Addr(nil), Err:(*net.DNSError)(0xc0001a0040)}
然后我做同样的事情并“解压”net.OpError 中包含的 net.DNSError:
dnsError := netOpError.Err.(*net.DNSError)
fmt.Printf("DNSError contains: %#v\n", dnsError)
---
DNSError contains: &net.DNSError{Err:"dial udp 169.254.169.254:53: connect: no route to host", Name:"doesnotexistkjdfhgsdfsdf.com", Server:"169.254.169.254:53", IsTimeout:false, IsTemporary:true, IsNotFound:false}
net.DNSError 不“包含”任何其他错误,所以对我来说,这表明它是链的底部和“真正的”错误(或者,至少是我想要处理的错误)。
问题是,这不是一个可行的方法,我不明白我们应该如何处理这个问题。在我发现最初的 SO 文章之前,我不知道 net.DNSError 是一个东西,或者我的错误可能是那种“类型”。
如果您不知道存在特定的错误类型,并且函数调用可能属于该类型,您怎么知道?
我对 Go 中的一般接口和类型的理解非常有限,我敢肯定这在这里没有帮助,但对我来说,在发生错误和知道要发生什么样的错误之间似乎有一个巨大的飞跃检查它可能是。我希望这个问题有意义!
【问题讨论】:
-
你可以查看这个帖子:go.dev/blog/go1.13-errors
-
如果您不知道 DNSError 存在,那么您为什么要关心处理它呢?你应该关心你所知道的事情,并以通用的方式处理其余的事情。
-
如果特定的错误类型与 API 的用户相关,那么可能应该记录这些不同的错误类型,以便用户知道要查找和正确处理的类型。这样,错误类型就成为 API 的一部分。
-
“我不明白如何在没有猜测或先验知识的情况下计算出提供这些功能的错误类型” - 这就是文档的用途。当错误类型相关时,文档应说明可能返回的类型。但正如 rustyx 指出的那样,如果您不知道错误可能是什么类型,那么它可能与您的应用程序逻辑无关。
标签: go error-handling go-interface