我知道通过执行以下操作来指定HTTP请求超时的常用方法:
httpClient := http.Client{
Timeout: time.Duration(5 * time.Second),
}
但是,我似乎无法弄清楚在跟踪HTTP请求时如何做同样的事情。以下是我正在处理的代码:
func timeGet(url string) (httpTimingBreakDown, error) {
req, _ := http.NewRequest("GET", url, nil)
var start, connect, dns, tlsHandshake time.Time
var timingData httpTimingBreakDown
timingData.url = url
trace := &httptrace.ClientTrace{
TLSHandshakeStart: func() { tlsHandshake = time.Now() },
TLSHandshakeDone: func(cs tls.ConnectionState, err error) { timingData.tls = time.Since(tlsHandshake) },
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
start = time.Now()
http.DefaultTransport.(*http.Transport).ResponseHeaderTimeout = time.Second * 10 // hacky way, worked earlier but don't work anymore
if _, err := http.DefaultTransport.RoundTrip(req); err != nil {
fmt.Println(err)
return timingData, err
}
timingData.total = time.Since(start)
return timingData, nil
}
我在goroutine中触发了这个函数。我的样本数据集是100个网址。所有goroutines都会激活,但最终程序会在30秒内结束,就像超时为30秒一样。
早些时候我做了同样的工作,使用hacky方法将其内部的默认值更改为10秒,任何花费太长时间,超时并且程序以10.xxx秒结束但现在以30.xx结束秒。
在这种情况下指定超时的正确方法是什么?
答案 0 :(得分:3)
我知道通过执行以下操作来指定HTTP请求超时的常用方法:
httpClient := http.Client{ Timeout: time.Duration(5 * time.Second), }
实际上,首选方法是在请求中使用context.Context。您使用的方法只是一个适用于简单用例的快捷方式。
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()
req = req.WithContext(ctx)
这种方法也可以很好地适应你的情况。