我不确定如何准确地表达这个问题,而且我看到其他人问过类似的问题,但并没有真正想出答案(这告诉我我问错了问题,但我不确定如何解决这个问题)。
我正在尝试学习一些基本的围棋,但我在第一个障碍中遇到了困难。
在我的测试代码中,我正在对一个不存在的域执行基本的 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 答案:
包“errors”有函数As,是解包特定的错误类型,包“net”有一个*DNSError类型。所以:
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) {
...
}
这段代码有效,但我对这个结论是如何得出的完全零了解。以下是我试图理解这一点的方法,我想知道我哪里出错了。我(模糊地)了解 .Is() 和 .As() 正在做什么,但我不明白的是如何在不猜测或先验知识的情况下计算出什么错误“类型”来提供这些功能。
我在这里查看了 client.get() 文档,其中说:
任何返回的错误都是 *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 中的一般接口和类型的理解非常有限,我确信这在这里没有帮助,但对我来说,在出现错误和知道要检查什么样的错误之间似乎有一个巨大的飞跃是。我希望这个问题是有道理的!