我在Go中创建了一个URL提取器,并且有一个要获取的URL列表。我向每个网址发送http.Get()
个请求并获得他们的回复。
resp,fetch_err := http.Get(url)
如何为每个Get请求设置自定义超时? (默认时间很长,这使得我的提取器非常慢。)我希望我的提取器有超过40-45秒的超时时间,之后它应该返回“请求超时”并转到下一个URL。
我怎样才能做到这一点?
答案 0 :(得分:223)
显然在Go 1.3 http.Client中有超时字段
timeout := time.Duration(5 * time.Second)
client := http.Client{
Timeout: timeout,
}
client.Get(url)
这对我来说已经成功了。
答案 1 :(得分:52)
您需要使用自己的Client设置自己的Transport 自定义拨号功能,包裹DialTimeout。
类似(完全未经测试)this:
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")
}
答案 2 :(得分:28)
要添加到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()
答案 3 :(得分:8)
快速而肮脏的方式:
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 45
这是在没有任何协调的情况下改变全球状态。但是你的网址提取器可能还可以。否则,请创建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)
...
以上没有测试过。
答案 4 :(得分:7)
如果您想根据请求执行此操作,为简便起见,错误处理将被忽略:
ctx, cncl := context.WithTimeout(context.Background(), time.Second*3)
defer cncl()
req, _ := http.NewRequest(http.MethodGet, "https://google.com", nil)
resp, _ := http.DefaultClient.Do(req.WithContext(ctx))
答案 5 :(得分:1)
您可以使用https://github.com/franela/goreq以简单的方式处理超时。
答案 6 :(得分:0)
timeout := time.Duration(5 * time.Second)
transport := &http.Transport{Proxy: http.ProxyURL(proxyUrl), ResponseHeaderTimeout:timeout}
这可能会有所帮助,但请注意,ResponseHeaderTimeout
仅在建立连接后开始。