英文:
Do we need to close the response object if an error occurs while calling http.Get(url)?
问题
在错误情况下,是否也需要关闭响应体呢?
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
}
defer res.Body.Close()
是的,在错误情况下也需要关闭响应体。以上代码中使用了 defer
关键字来延迟执行 res.Body.Close()
,无论是否发生错误,都会确保在函数返回前关闭响应体。这样可以避免资源泄漏和提高代码的可靠性。
英文:
In the following code is it also necessary to close the response body in the error case:
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
}
defer res.Body.Close()
答案1
得分: 19
一般的概念是,当一个函数(或方法)有多个返回值时,其中一个是error
,应该首先检查错误,只有在错误为nil
时才继续执行。如果有错误,函数应该返回其他(非错误)值的零值。如果函数的行为不同,应该进行文档记录。http.Get()
没有记录这种偏差。
所以应该这样处理:
res, err := http.Get(url)
if err != nil {
log.Printf("错误:%s\n", err)
return
}
defer res.Body.Close()
// 读取/处理响应体
注意:
正如JimB也确认的那样,如果返回的错误不是nil
,即使响应不是nil
,我们也不必关闭它。在重定向错误的情况下,非nil
的响应可能包含有关重定向失败的上下文和更多信息。详细信息请参见下面的说明:
http.Get()
大部分时间都遵循这个一般概念:如果有错误,它会返回nil
的响应:
return nil, someError
然而,检查client.go
,未导出的方法Client.doFollowingRedirects()
,目前在第427行:
if redirectFailed {
// Go 1兼容性的特殊情况:如果CheckRedirect函数失败,同时返回响应和错误。
// 参见https://golang.org/issue/3795
return resp, urlErr
}
因此,由于向后兼容性问题,如果重定向失败,它可能同时返回非nil
的响应和非nil
的错误。
另一方面,如果resp
是nil
,尝试调用resp.Body.Close()
将导致运行时恐慌。
因此,如果我们想在这种情况下关闭响应体,可以这样写(只有当resp
不是nil
时才能关闭):
res, err := http.Get(url)
if err != nil {
log.Printf("错误:%s\n", err)
}
if res != nil {
defer res.Body.Close()
// 读取/处理响应体
}
或者:
res, err := http.Get(url)
if err != nil {
log.Printf("错误:%s\n", err)
}
if res == nil {
return
}
defer res.Body.Close()
// 读取/处理响应体
http.Response
的文档保证即使没有响应数据,Response.Body
也不会是nil
:
// http Client和Transport保证Body始终非nil,即使在没有响应体或零长度响应体的情况下。
但是,如果错误不是nil
,则不必关闭非nil
的响应体。
英文:
General concept is that when a function (or method) has multi return values one being an error
, error should be checked first and only proceed if the error is nil
. Functions should return zero values for other (non-error) values if there is an error
. If the function behaves differently, it should be documented. http.Get()
does not document such deviation.
So it should be handled like this:
res, err := http.Get(url)
if err != nil {
log.Printf("Error: %s\n", err)
return
}
defer res.Body.Close()
// Read/work with body
Notes:
As JimB confirms too, if a non-nil
error is returned, even if the response is non-nil
, we don't have to close it. In case of a redirection error the non-nil
response may hold context and further information about where following the redirect failed. See details below:
http.Get()
honors the general concept "most of the time": it returns nil
response if there is an error:
return nil, someError
However checking client.go
, unexported method Client.doFollowingRedirects()
, currently line #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
}
So due to a backward compatibility issue it may return a non-nil
response and a non-nil
error at the same time, if redirection fails.
On the other hand trying to call resp.Body.Close()
if resp
is nil
will cause a run-time panic.
So if we want to close response body in this case, it could look like this (can only be closed if resp
is not nil
):
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
}
Or:
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
The doc of http.Response
guarantees that Response.Body
will not be nil
even if there is no response data:
// 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.
But if the error is not nil
, you don't have to close the non-nil
response body.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论