Golang中如何检查`client.Do()`的错误?

Golang中如何检查client.Do()的错误? 在我的Go程序中,我按如下方式发起请求:

// 准备请求
req, err := http.NewRequest("GET", path, nil)
if err != nil {
    log.Fatalln("Error preparing request.", err)
}
client := &http.Client{Timeout: time.Second * 12}

// 执行请求
request, err := client.Do(req)
if err != nil {
    log.Fatalln("Failed to make request.", err)
}
defer request.Body.Close()

我遇到的其中一个错误是:

 Get https://www.maps.google.com: dial tcp: lookup www.maps.google.com: no such host

我在调整代码以检查“no such host”错误时遇到了困难。该如何实现呢?

通过查阅client.Do()文档,我了解到返回的错误类型为*url.Error。我在这里找到了该错误的定义,并注意到Error()函数返回一个字符串。或许我可以检查这个字符串来识别“no such host”错误?

我尝试过的方法包括:

if string(err) == url.InvalidHostError() {
    log.Println("Host not found.")
}

if err(*url.Error) == url.InvalidHostError() {
    log.Println("Host not found.")
}

if strings.Contains(err.(*Error), "no such host") {
    log.Println("Host not found.")
}

我已经通过谷歌搜索、阅读错误处理相关文章、研究url.go的代码,并查阅了我手头的《Go编程语言》一书。但我仍感觉对这个主题理解不够深入,陷入了困境。

欢迎任何建议!


更多关于Golang中如何检查`client.Do()`的错误?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

这个类型

type Error struct {
        Op  string
        URL string
        Err error
}

包含三个成员 OpURLErr,你可以这样访问:

fmt.Println(err.Err)

更多关于Golang中如何检查`client.Do()`的错误?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Juk:

获取 https://www.maps.google.com:拨号 tcp:查找 http://www.maps.google.com:无此主机

你不需要过多检查错误。在浏览器中验证后发现所声称的地址并不存在。

**www.maps.google.com** 的服务器 IP 地址无法找到。

可能你想说的是 maps.google.com

但也许他们想检查错误信息,以便提供更友好的用户提示?

我处理的许多——如果不是全部——客户在遇到类似错误时,会立即联系内部IT部门,就因为错误信息里出现了tcp这个词。这可是网络相关的问题……他们甚至不会继续阅读到关键部分。

在这种情况下,我的做法是使用err.Error()获取字符串表示形式,然后对字符串化的错误信息进行正则表达式匹配,同时祈祷错误信息的结构永远不会改变。

err.Error()

感谢大家的积极参与,非常感激。😊

lutzhorn: 你可以访问:

fmt.Println(err.Err)

这让我得到了错误信息:

err.Err undefined (type error has no field or method Err)

这让我感到困惑,因为我明白你的意思。

NobbZ: 在这种情况下,我通常使用 err.Error() 来获取字符串表示形式,然后对字符串化的错误应用一些正则表达式,祈祷错误消息的结构永远不会改变。

谢谢你的想法,这是个不错的方法。我已经调整了我的代码,现在这样做:

request, err := client.Do(req)
if err != nil {
    if strings.Contains(err.Error(), "no such host") {
        log.Printf("Host not found: %s", path)
    } else {
        log.Println("Failed to make request.", err)
    }
    return ""
}
defer request.Body.Close()

这样运行得很好!😊(虽然需要更精确一些,并且可能需要第二次尝试,但这是以后的事情。)

geosoft1: 你不需要太多的错误检查。在浏览器中检查,声称的地址不存在。

确实如此,说得好。但我的应用程序希望检查100万个域名,不想逐个检查每个域名的网站地址是什么。

要检查client.Do()返回的错误是否为"no such host"错误,你需要使用类型断言来访问底层的*url.Error,然后检查其Err字段。以下是一个完整的示例:

req, err := http.NewRequest("GET", path, nil)
if err != nil {
    log.Fatalln("Error preparing request.", err)
}
client := &http.Client{Timeout: time.Second * 12}

request, err := client.Do(req)
if err != nil {
    // 检查是否为URL错误
    if urlErr, ok := err.(*url.Error); ok {
        // 检查底层错误是否为DNS查找错误
        if netErr, ok := urlErr.Err.(*net.OpError); ok {
            if dnsErr, ok := netErr.Err.(*net.DNSError); ok && dnsErr.IsNotFound {
                log.Println("Host not found:", dnsErr.Name)
                // 处理主机不存在的情况
                return
            }
        }
    }
    log.Fatalln("Failed to make request.", err)
}
defer request.Body.Close()

或者,你也可以使用更简洁的错误链检查方式:

req, err := http.NewRequest("GET", path, nil)
if err != nil {
    log.Fatalln("Error preparing request.", err)
}
client := &http.Client{Timeout: time.Second * 12}

request, err := client.Do(req)
if err != nil {
    var dnsErr *net.DNSError
    if errors.As(err, &dnsErr) && dnsErr.IsNotFound {
        log.Println("Host not found:", dnsErr.Name)
        // 处理主机不存在的情况
        return
    }
    log.Fatalln("Failed to make request.", err)
}
defer request.Body.Close()

在第二个示例中,errors.As函数会遍历错误链,查找匹配的*net.DNSError类型,如果找到并且IsNotFound为true,则表示是"no such host"错误。

对于你提到的字符串检查方法,虽然技术上可行,但不推荐,因为错误消息可能因不同系统或Go版本而变化。使用类型系统进行检查更加可靠。

回到顶部