如何在 Golang 设置 http. Get()请求的超时?

我在 Go 中创建了一个 URL 获取器,并且有一个要获取的 URL 列表。我向每个 URL 发送 http.Get()请求并获得它们的响应。

resp,fetch_err := http.Get(url)

如何为每个 Get 请求设置自定义超时?(默认时间非常长,这使得我的获取器非常慢。)我希望我的抓取器有一个大约40-45秒的超时时间,之后它应该返回“请求超时”并转移到下一个 URL。

我怎么才能做到呢?

151374 次浏览

一个又快又脏的方法:

http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45

这是全球状态的变异。然而,对于您的 url 获取器来说,这可能没有问题。否则,创建 http.RoundTripper的私有实例:

var myTransport http.RoundTripper = &http.Transport{
Proxy:                 http.ProxyFromEnvironment,
ResponseHeaderTimeout: time.Second * 45,
}


var myClient = &http.Client{Transport: myTransport}


resp, err := myClient.Get(url)
...

上面的内容都没有经过测试。

您需要设置自己的 客户和自己的 交通工具,后者使用 围绕 拨号超时的自定义拨号函数。

类似(完全的 未经测试) 这个:

var timeout = time.Duration(2 * time.Second)


func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}


func main() {
transport := http.Transport{
Dial: dialTimeout,
}


client := http.Client{
Transport: &transport,
}


resp, err := client.Get("http://some.url")
}

要添加到 Volker 的答案中,除了连接超时之外,如果您还希望设置读/写超时,您可以执行以下操作

package httpclient


import (
"net"
"net/http"
"time"
)


func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) {
return func(netw, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(netw, addr, cTimeout)
if err != nil {
return nil, err
}
conn.SetDeadline(time.Now().Add(rwTimeout))
return conn, nil
}
}


func NewTimeoutClient(connectTimeout time.Duration, readWriteTimeout time.Duration) *http.Client {


return &http.Client{
Transport: &http.Transport{
Dial: TimeoutDialer(connectTimeout, readWriteTimeout),
},
}
}

这段代码经过了测试,并且正在生产环境中运行 Https://gist.github.com/dmichael/5710968

请注意,您将需要为每个请求创建一个新的客户机,因为 conn.SetDeadline引用将来从 time.Now()发出的一个点

显然在 Go 1.3 http.Client中有超时字段

client := http.Client{
Timeout: 5 * time.Second,
}
client.Get(url)

这招对我很管用。

如果希望按请求执行,则为简洁起见忽略了错误处理:

ctx, cncl := context.WithTimeout(context.Background(), time.Second*3)
defer cncl()


req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "https://google.com", nil)


resp, _ := http.DefaultClient.Do(req)
timeout := time.Duration(5 * time.Second)
transport := &http.Transport{Proxy: http.ProxyURL(proxyUrl), ResponseHeaderTimeout:timeout}

这可能会有所帮助,但是请注意,ResponseHeaderTimeout仅在建立连接之后才启动。

在 Go http模块中有几个客户端超时,并且在当前答案中有一些这些超时的示例。

这里有一个图片来说明客户端超时参考 < a href = “ https://blog.Cloudflare.com/The-complete-guide-to-golang-net-http-timeouts/”rel = “ nofollow noReferrer”> 完整的 Go net/http 超时指南 enter image description here

有两种方法可以设置 HTTP 请求的超时时间

  • 客户端
client := http.Client{
Timeout: 3 * time.Second,
}
resp, err := client.Do(req)
  • 背景
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, URL)

他们之间的区别是

  • 使用上下文是在使用 客户端超时可能应用于所有请求传递到 Do方法时客户端具有的特定请求。
  • 如果您想为每个请求专门设置 deadline/timeout,那么使用上下文,否则,如果您想为每个出站请求设置1个超时,那么使用客户端超时就足够了。