2015-10-20 111 views
2

我正在使用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

回答

4

如果您只想使用解碼器對單個對象進行解碼,則可以使用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