2015-09-28 30 views

回答

13

一般概念是,當一個函數(或方法)具有多返回值一個是error,誤差應首先檢查,如果錯誤是nil,則僅執行。如果存在error,函數應該爲其他(非錯誤)值返回零值。如果函數的行爲不同,它應該被記錄下來。 http.Get()沒有記錄這種偏差。

所以應該這樣處理:

res, err := http.Get(url) 
if err != nil { 
    log.Printf("Error: %s\n", err) 
    return 
} 

defer res.Body.Close() 
// Read/work with body 

注:

由於JimB確認過,如果返回了非nil錯誤,即使響應是非 - nil,我們不必關閉它。如果發生重定向錯誤,則非響應可能包含上下文以及關於重定向失敗後的位置的更多信息。詳情請見下文:

http.Get()榮譽的一般概念「大部分時間」:返回nil響應,如果有一個錯誤:

return nil, someError 

但是檢查client.go,未導出的方法Client.doFollowingRedirects(),目前線#427:

if redirectFailed { 
    // Special case for Go 1 compatibility: return both the response 
    // and an error if the CheckRedirect function failed. 
    // See https://golang.org/issue/3795 
    return resp, urlErr 
} 

所以由於向後兼容性問題,它可能會返回在同一時間非0​​響應和非nil錯誤,我f重定向失敗。如果respnil將導致運行時恐慌。

因此,如果我們要關閉響應主體在這種情況下,它可能是這樣的(只能暫時封閉respnil):

res, err := http.Get(url) 
if err != nil { 
    log.Printf("Error: %s\n", err) 
} 
if res != nil { 
    defer res.Body.Close() 
    // Read/work with body 
} 

或者:

res, err := http.Get(url) 
if err != nil { 
    log.Printf("Error: %s\n", err) 
} 
if res == nil { 
    return 
} 

defer res.Body.Close() 
// Read/work with body 

的doc http.Response保證即使沒有響應數據,Response.Body也不會是nil

// The http Client and Transport guarantee that Body is always 
// non-nil, even on responses without a body or responses with 
// a zero-length body. 
+4

如果您得到一個需要關閉錯誤的響應主體,那是需要提交的錯誤。在這種情況下,您應該爲身體設置一個空的靠近,這樣只會使關閉不會驚慌。 – JimB

+0

@JimB這就是我的想法。感謝您的確認。將編輯答案。 – icza

+3

我去了,並且雙重檢查了客戶端代碼,並且在重定向錯誤返回Response的情況下,Body已經關閉,並且連接被釋放。雖然它並沒有受到傷害,但在客戶端出錯後,永遠不需要'推遲resp.Body.Close()'。 – JimB

相關問題