Go HTTP 包:为什么读取完 res.Body 后需要关闭它?

dem*_*mee 0 go

请参阅此处的示例https://pkg.go.dev/net/http#example-Get。下面也有截图:

func main() {
    res, err := http.Get("http://www.google.com/robots.txt")
    if err != nil {
        log.Fatal(err)
    }
    body, err := io.ReadAll(res.Body)
    res.Body.Close() // Why!?
    if res.StatusCode > 299 {
        log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s", body)
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么我需要关闭res.Body.Close()第7行。我没有打开它。我在如果我不关闭response.Body会发生什么?中看到了解释。我明白文档是这么说的。

有没有更好的方法来解决这个问题?

我认为这违反了开闭原则。我认为如果 ReadAll 打开了 steam,它应该将其关闭。Go 中通常是这样完成这些事情的吗?

col*_*tor 7

来自http.Client Do()文档:

...如果正文未读取到 EOF 并关闭,则客户端的底层 RoundTripper(通常为 Transport)可能无法重新使用与服务器的持久 TCP 连接来执行后续的“保持活动”请求。

简而言之,如果您不遵循此建议,您将在执行请求时在程序中累积“死”http 连接 - 但永远不会清理和/或重用。随着时间的推移,您的程序的性能将会下降 - 并且取决于生成的连接数量 - 您可能会耗尽有限的资源,例如处理网络连接的文件描述符。