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) 

我不知道这两种方法如何相互作用。

所以问题是,我如何确保整个响应已被读取,以便以后可以重新使用连接来处理其他请求?

+1

嗯。也许最简单的是自己实现旧的行为:'defer func(){io.Copy(ioutil.Discard,resp.Body); resp.Body.Close()}()'。 – twotwotwo

+0

也许在** decoder.Decode(data)之后,**返回那么你已经读取了所有的数据。 – nvcnvn

+1

如果您只希望在身体中有一个合理大小的json响应,请不要打扰解码器。使用ReadAll和json.Unmarshal。 – JimB

如果您只想使用解码器对单个对象进行解码,则可以使用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