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

标签 http go error-handling deferred

在下面的代码中是不是也需要在错误情况下关闭响应体:

res, err := http.Get(url)

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

defer res.Body.Close()

最佳答案

一般概念是,当一个函数(或方法)有多个返回值一个是 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,我们也不必关闭它。在重定向错误的情况下,非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
}

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

另一方面,如果 respnil 则尝试调用 resp.Body.Close() 将导致运行时 panic 。

所以如果我们想在这种情况下关闭响应体,它可能看起来像这样(只有当 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
}

或者:

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

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.

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

关于http - 如果在调用 http.Get(url) 时发生错误,我们是否需要关闭响应对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32818472/

相关文章:

json - 在 Go 中解码时输入检查 json 值

mongodb - Golang 更新 mongodb 中的现有文件

r - UseMethod中的错误(“group_vars”): no applicable method for 'group_vars' applied to an object of class “factor”

performance - JMeter,发布所有表单数据

node.js - 收到第一个字节后停止 superagent(只获取重定向 url)

http - http post请求中的Angular2超时

php - HTTP_RAW_POST_DATA 的安全问题

go - 关于主例程和子例程同时监听同一个 channel 的问题

c++ - 获取异常类型

javascript - 使用 Node.js,是否有一些语义可以告诉我代码何时要离开当前堆栈?