在golang多个请求后关闭响应主体多次(Close response body multiple

2019-09-30 11:32发布

在这篇文章中,指出response.Body应该被关闭,以避免资源泄漏。 它也显示在在概览例子HTTP包godoc 。

在我的测试代码,我发送多个请求,试图与API

resp, err := http.DefaultClient.Do(req)

多次在相同的功能。 这是一个不好的做法? 在这种情况下,我写defer resp.Body.Close()他们每个人之后,或者只是一次?

url := server.URL + "/ticket/add"                                       
reader = strings.NewReader(`{"id": "test1", "detail": "test1"}`)        
req, err := http.NewRequest("POST", url, reader)                        
assert.Nil(t, err)               

resp, err := http.DefaultClient.Do(req)                                 
assert.Nil(t, err)                                                      

defer resp.Body.Close()                                                 

assert.Equal(t, http.StatusCreated, resp.StatusCode)                    
// add a ticket with same id                                            
reader = strings.NewReader(`{"id": "test1"}`)                           
req, err = http.NewRequest("POST", url, reader)                         
assert.Nil(t, err)                                                      

resp, err = http.DefaultClient.Do(req)                                  
assert.Nil(t, err)                                                      
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)   

一个相关的问题,在服务器端,即内部func(w http.ResponseWriter, r *http.Request)是否有必要关闭请求主体呢?

Answer 1:

是的,你需要关闭两种反应。 推迟一个调用resp.Body.Close不以某种方式影响其他。 在*http.Response在每种情况下不同,它们都可以被推迟。

在服务器端,你并不需要关闭Request.Body -从http.Request文档 :

// The Server will close the request body. The ServeHTTP
// Handler does not need to.


Answer 2:

坏习惯

如果你没有重用resp变量,这将是显而易见的,你是在处理不同的响应情况其中的每一个都必须关闭。

不要发送一个HTTP请求,并返回一个HTTP响应 (实例)...

因此,不好的做法是不要做几个请求,但重复使用相同的变量数响应。 它会导致代码unobviousness。 并产生从未敲定不可达的对象。

延迟执行

一个defer语句推动一个函数调用到列表中。 保存通话清单周围的函数返回后执行。

如果已经预定了单个或几个defer参照同一个变量只有最后赋值给变量对象的方法(好几次被执行死刑红defer S)。

游乐场用一个例子

关闭Response.Body

Response文件 :

这是调用者负责近身。

所以,通常你必须关闭每个Response.Body

垃圾收集与定稿(编辑)

垃圾收集器调用结合收集对象终结关闭文件,连接,并做其他清理动作。 而且也没有终结结合Body由默认的对象。

您改善片断:

// ...a lot of code
resp_one, err := http.DefaultClient.Do(req)                                 
 // BTW, `assert.Nil` just returns whether the assertion was successful (bool) not terminates a test.
if assert.Nil(t, err) == true {
    defer resp_one.Body.Close()                                                 
}

// ...a lot of code
resp_two, err = http.DefaultClient.Do(req)                                  
if assert.Nil(t, err) == true {
    defer resp_two.Body.Close()
}


文章来源: Close response body multiple times after multiple requests in golang