如果在调用http.Get(url)时发生错误,是否需要关闭响应对象?

Pra*_*ant 12 error-handling http go deferred

在以下代码中,还需要在错误情况下关闭响应主体:

res, err := http.Get(url)

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

defer res.Body.Close()
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 18

一般概念是,当函数(或方法)具有多个返回值时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
Run Code Online (Sandbox Code Playgroud)

笔记:

正如JimB所证实的那样,如果nil返回非错误,即使响应是非错误的nil,我们也不必关闭它.在重定向错误的情况下,非nil响应可以保持上下文以及关于重定向之后的位置的进一步信息.详情如下:

http.Get()尊重"大多数时候"的一般概念:nil如果出现错误,它会返回响应:

return nil, someError
Run Code Online (Sandbox Code Playgroud)

但是,检查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
}
Run Code Online (Sandbox Code Playgroud)

因此,由于向后兼容性问题,如果重定向失败,它可能同时返回非nil响应和非nil错误.

在另一方面试图调用resp.Body.Close()是否resp就是nil将导致运行时的恐慌.

因此,如果我们想在这种情况下关闭响应体,它可能看起来像这样(只有在resp不是时才能关闭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
}
Run Code Online (Sandbox Code Playgroud)

要么:

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
Run Code Online (Sandbox Code Playgroud)

即使没有响应数据也不会出现的http.Response担保文件:Response.Bodynil

// 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.
Run Code Online (Sandbox Code Playgroud)

如果错误不是nil,则不必关闭非nil响应主体.

  • 如果你得到一个需要关闭错误的响应主体,那就是需要提交的错误.在这种情况下,你应该有一个空的nop靠近身体,只有在那里使关闭而不是恐慌. (4认同)
  • 我去了并仔细检查了客户端代码,在重定向错误返回Response的单例中,Body已经关闭,连接被释放.虽然它没有受到伤害,但是在客户端错误之后永远不需要"推迟resp.Body.Close()". (4认同)