Go - HTTP请求,JSON,重用连接
问题描述:
我正在使用Go通过HTTPS发出很多请求,并且遇到了不重用连接和端口用尽的问题。我所做的请求是以JSON格式返回数据的API,然后将json.Decode
转换为Go值。Go - HTTP请求,JSON,重用连接
根据我在本网站上遇到的问题(#1,#2),为了让Go重用连接的其他请求,我必须在关闭前阅读整个响应的主体(注意这不是总是行为,如here所述)。
Previously the HTTP client's (*Response).Body.Close would try to keep
reading until EOF, hoping to reuse the keep-alive HTTP connection...
在一个典型的例子,我会用在前面的链接所示的例子,像这样:
ioutil.ReadAll(resp.Body)
,但因为我通过代码拉出JSON的数据是这样的:
...
req, _ := http.NewRequest("GET", urlString, nil)
req.Header.Add("Connection", "keep-alive")
resp, err = client.Do(req)
defer resp.Body.Close()
...
decoder := json.NewDecoder(resp.Body)
decoder.Decode(data)
我不知道这两种方法如何相互作用。
所以问题是,我如何确保整个响应已被读取,以便以后可以重新使用连接来处理其他请求?
答
如果您只想使用解码器对单个对象进行解码,则可以使用More()
方法来查看流中是否还有更多需要读取的对象。
decoder := json.NewDecoder(resp.Body)
err := decoder.Decode(data)
if err != nil {
// handle err
}
if decoder.More() {
// there's more data in the stream, so discard whatever is left
io.Copy(ioutil.Discard, resp.Body)
}
您也可以在每次调用时推迟复制,但这样可以更轻松地处理或记录是否有意外的数据或错误。
+0
是的,我碰到'More()',我不确定它是否正在做我想要的。谢谢! – bawjensen
嗯。也许最简单的是自己实现旧的行为:'defer func(){io.Copy(ioutil.Discard,resp.Body); resp.Body.Close()}()'。 – twotwotwo
也许在** decoder.Decode(data)之后,**返回那么你已经读取了所有的数据。 – nvcnvn
如果您只希望在身体中有一个合理大小的json响应,请不要打扰解码器。使用ReadAll和json.Unmarshal。 – JimB