【问题标题】:is resp.Body.Close() necessary if we don't read anything from the body?如果我们不从正文中读取任何内容,是否需要 resp.Body.Close()?
【发布时间】:2016-01-21 23:59:15
【问题描述】:

我有一个函数,它只发出一个 get 请求来检查状态代码。它不会从身体中读取任何内容。我还应该用resp.Body.Close() 结束函数吗?

调用者在读取完 resp.Body 后应该关闭它。如果 resp.Body 没有关闭,客户端的底层 RoundTripper(通常是 Transport)可能无法重新使用到服务器的持久 TCP 连接来进行后续的“keep-alive”请求。

【问题讨论】:

  • 来自文档:“客户端完成后必须关闭响应正文:”。从中读取任何内容都不会改变问题。
  • @dystroy 我已经用我所指的 godoc 段落更新了问题
  • 好吧。我不明白你为什么要问。为什么要避免关闭身体?
  • 显然这可以通过添加 .Close() 来解决,无论如何。但我想要更多关于学习内部结构的信息。 .Close() 做什么?什么时候需要?
  • 必须致电Close,这是必须的。

标签: go


【解决方案1】:

是的。当您调用 http.Get 时,该函数会在读取所有 HTTP 标头后立即返回响应。尚未阅读响应的正文。 Response.Body 是与服务器的网络连接的包装器。当您从中读取时,它会下载响应的正文。

.Close() 告诉系统您已完成网络连接。如果您尚未阅读响应正文,默认的 http 传输将关闭连接。 (如果主体已被读取,传输只能重用连接,因为如果它重用与未读主体的连接,则使用该连接发出的下一个请求将收到前一个请求的响应!)

因此,如果您发出多个请求,则读取正文通常比简单的 Close()ing 更有效 - 特别是在创建成本相对较高的 TLS 连接时。

如果您不需要响应的正文,则应使用 Head 而不是 Get。 Head 不需要阅读 关闭响应正文。

【讨论】:

  • “因此,如果您提出多个请求,阅读正文通常比简单地关闭()更有效”,@andybalholm。您能否进一步详细说明这一点? :)
  • 另一个查询 :) 我做了一个人为的例子:play.golang.org/p/TlNSuGCfi3。 *请注意,由于不支持 http 协议,它将在 goplayground 中失败,但是当我在我的机器上运行时,每个响应都与其 url 正确映射,而不是像您上面描述的那样,相同的连接会收到以前的请求响应。我做得对吗?
  • @Roylee,这是关于当所有请求都发往同一服务器时(例如https://golang.orghttps://golang.org/doc/)。如果响应主体根本没有关闭,则每个请求都将在单独的 TCP 连接上发送,并且两个连接都不会关闭。如果主体在未读取的情况下关闭,则每个请求都会拨号并关闭自己的 TCP 连接。但是,如果您阅读并关闭正文,则第二个请求可能会在与第一个连接相同的连接上发送,从而节省了在第二个连接上用于 TCP 和 TLS 握手的时间。
  • @Roylee,关于获取上一个请求的响应的部分是在讨论如果传输重用具有未读正文的底层连接会发生什么,而不是如果你从未调用 Close 会发生什么。我希望我的编辑能让它更清晰。
  • 哦,是的!非常感谢您抽出时间回复。彻底打消了我的疑惑,我现在明白了! :)
猜你喜欢
  • 2017-06-29
  • 2020-03-24
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
相关资源
最近更新 更多