Golang中如何正确关闭HTTP响应

Golang中如何正确关闭HTTP响应 你好,

我想请教一下。 如果我只对HTTP响应的状态码和Cookie感兴趣,是否还需要关闭响应体?

谢谢

8 回复

感谢回复

更多关于Golang中如何正确关闭HTTP响应的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,它会释放连接。

对于简单的应用程序来说无关紧要,但对于基于重型基础设施的应用程序和高负载场景来说,确实很重要。

在我最初的测试中,即使对于空或零长度(嗯,我们该如何称呼它们)的响应体,不读取内容直接关闭仍然有效。

但在延迟执行前请检查响应体是否为空。如果响应体为空,会导致程序崩溃。表情

据我所知,关闭成功请求的空响应体不会报错(对此不太确定,也不确定我们所说的空响应体是否指同一概念),但即使会报错,使用 defer 调用 Close() 也只会让你错过错误(除非在封闭函数中返回命名错误并赋值),而不会引发恐慌。我是否遗漏了什么?

为了补充一些信息,http客户端的文档对于Get、Post和PostForm方法有以下说明:

// 当err为nil时,resp始终包含一个非空的resp.Body。 // 调用方在读取完响应体后应关闭resp.Body。

但随后文档对Do()方法(上述所有方法都会调用它)有这样的说明:

// 出现错误时,可以忽略任何Response。非空的Response与非空的error // 仅发生在CheckRedirect失败时,即便如此 // 返回的Response.Body也已经被关闭。

因此,在检查响应是否出错后延迟关闭响应体是可行的,例如:

resp, err := http.Get("http://example.com/")
if err != nil {
    // 处理错误,无需担心响应体
}
defer resp.Body.Close() // 当error为nil时延迟关闭响应体

在Go语言中,无论你是否只对HTTP响应的状态码和Cookie感兴趣,都必须正确关闭HTTP响应体。如果不关闭响应体,会导致资源泄漏(如TCP连接未释放),可能影响应用程序的性能和稳定性。

根据Go的net/http包文档,即使你只读取部分响应体或完全不读取,也必须调用Body.Close()来确保连接可以被复用或正确关闭。最佳实践是使用defer语句来确保响应体在函数返回前被关闭。

以下是一个示例代码,展示如何正确处理HTTP响应:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    resp, err := http.Get("https://example.com")
    if err != nil {
        fmt.Printf("Error making request: %v\n", err)
        return
    }
    defer resp.Body.Close() // 确保响应体被关闭

    // 访问状态码和Cookie
    fmt.Printf("Status Code: %d\n", resp.StatusCode)
    cookies := resp.Cookies()
    for _, cookie := range cookies {
        fmt.Printf("Cookie: %s=%s\n", cookie.Name, cookie.Value)
    }

    // 即使不读取响应体,也必须关闭它
}

在这个例子中:

  • 使用defer resp.Body.Close()确保响应体在函数退出时被关闭。
  • 你可以安全地访问resp.StatusCoderesp.Cookies(),而无需读取响应体内容。
  • 如果忽略关闭响应体,可能会导致文件描述符耗尽或连接池问题,特别是在高并发场景下。

记住,这是Go语言中处理HTTP响应的标准做法,必须始终遵循。

回到顶部