douju2599 2015-09-28 08:17
浏览 130
已采纳

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

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
", err)
}

defer res.Body.Close()
  • 写回答

1条回答 默认 最新

  • douque9815 2015-09-28 09:40
    关注

    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
    ", 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
    ", 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
    ", 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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 MATLAB中streamslice问题
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序