go 里面的 http response body 必须 close 是不是很不合理呀

302 天前
 zihuyishi
基本上每个新人写 http 请求都容易忘记这个,然后造成 goroutine 的泄漏。所以 http 请求基本都要实现一个 util 避免这种事情。
然后就是 close 在 Response.Body 上而不是 Response 本身,直觉上 close response 更符合普遍的逻辑吧。虽然可以理解是因为 body 和 response 生命周期不一样,但是用起来还是感觉不太协调
4315 次点击
所在节点    Go 编程语言
47 条回复
pluto1
301 天前
作为一个官方库肯定是要考虑到所有场景的,就像上面说的视频,或者还有很多需要不断读取的场景。
至于 Close 哪个的话这个就另说了,我个人感觉 Close body 好像合理一点。
顺便提醒下楼上的,defer 前一定要检查 body 是不是 nil ,不然如果 body 出现 nil 的情况,defer 执行的时候我记得是会 panic 的
lvlongxiang199
301 天前
我觉得很合理. `resp.Body` 就是个 reader 跟 fileReader 类似, 区别就是这是别人帮你 open 然后把 ownership move 给你, 负责 close 是用户的事, 你觉得 fileReader 必须 close 是不是合理的 ?
虽然对于大部分调用 rest api 的情况, 是把 reader 内的读出来, 之后 close. 但是对于需要流式获取的场景并不合适(比如: 实时视频流, 大文件), 按我的理解, 进入标准库的东西, 得适配普遍的场景, 而非 rest api 这种单一场景
crackidz
301 天前
语法糖也是要关闭的,只是不需要你手工关闭而已。response 对象的话包含了很多的其他内容,即使允许 close response 也能读取其中的其他信息,这其实很反直觉的。
holulu
301 天前
觉得不合理就换个语言吧,没必要纠结这些问题,不同的语言设计就不一样,要么自己设计一种符合自己习惯的。
kingofzihua
301 天前
用 CI 工具,golangci-lint 支持检测 bodyclose
CodeCodeStudy
301 天前
所以就要用到框架啊,让框架来处理这些底层的、琐碎的事情
maigebaoer
301 天前
我也遇到过这个坑😅😅😅
gamexg
301 天前
@pluto1 #21

看文档,至少官方实现 Body 不会出现 nil 的情况.
我一直没检查过 body 是否为 nil

Body represents the response body.
The response body is streamed on demand as the Body field is read. If the network connection fails or the server terminates the response, Body.Read calls return an error.
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. It is the caller's responsibility to close Body. The default HTTP client's Transport may not reuse HTTP/1.x "keep-alive" TCP connections if the Body is not read to completion and closed.
6diyipi
301 天前
文档就不看,出了问题逼逼赖赖。 官方库功能又不是为了满足你一个人, 想偷懒用 https://github.com/go-resty/resty
gamexg
301 天前
我是习惯了,
经常手写 net.Dial ,Close 是接着就会跟着的.

其实我感觉应该是标准库为了提供足够的灵活性,
按 golang 语言逻辑,如果不提供关闭,那么基本就只能内部实现 io.ReadAll ,那么意味着超大/超长延迟的响应会占用很大内存/很长时间.对于一些情况会有很大的影响.
例如我读取一个很长的 api 响应,是直接对着 body 这个流进行解析,而不是全部读取到内存再处理.
AoEiuV020JP
301 天前
@jinliming2 #18 图的是方便,具体用不用肯定是需要开发者自己斟酌的,
比如,上手学习测试, 请求 json api ,网页下载解析,都可能可以用,
性能表现之类肯定比不过流处理,但高级语言服务场景也不是时时刻刻都要扣这一点点性能,所以我说这种细节坑在 c/c++没有不合理,但放在现代语言就显得不合群了,
AoEiuV020JP
301 天前
@lvlongxiang199 #12 没有哪个高级语言是不提供流读取的, 没有人会把二进制大文件转字符串读到内存里的,
别给你个糖你就不吃饭了,饿死了怪别人给你糖,
lvlongxiang199
301 天前
@AoEiuV020JP
> 高级一点的现代语言都有封装一些方便的方法,比如直接把 body 完整读取转成字符串并 close
我的意思是, 这种封装挪到第三方库就行了, 没必要放到标准库, 这东西的使用场景很有限. 流式读取的应用场景更广泛, []byte, string 都可以看作是流


ps: **请你好好说话**
lvlongxiang199
301 天前
@AoEiuV020JP 我仅仅说你提供的这个封装不适合处理这种情况, 没说 golang 没提供这种处理. io.Reader 就是一个流
iseki
301 天前
Go 标准库很多 API 设计得都比较有特色。抛开 Go 不谈对于 HTTP 库一个典型设计是 response / body 都有独立的 close ,response 的关闭会导致 body 被连带关闭。
AoEiuV020JP
301 天前
@lvlongxiang199 #33 我想说的就是你这种站在 c/c++视角想问题的,落后几十年了,
要说不必须,那连 http 整个都不是必须的,都可以移到第三方库,你觉得是为什么 go 要自带 http 功能,
现代语言提供必要功能之外的服务是很正常的事,毕竟现代每一个编程语言的出现都是为了解决已有语言的痛点,那就必定会提供不必要但是方便的东西,
这方面 go 就感觉不上不下的,关键总有人把 go 拉到 c/c++这边把各种不方便合理化,
我的观点是,go 如果哪天想开了加上这类不必要的方法也是理所当然的,
AoEiuV020JP
301 天前
@lvlongxiang199 #33 在我这里,反问=阴阳怪气=不好好说话,
AoEiuV020JP
301 天前
@lvlongxiang199 #34 我的意思就是糖不需要管饱,这种封装方法不需要解决所有情况,有就可以了,能用的时候可以提供方便就可以了, 不需要管不适用的情况,
Nazz
301 天前
http 协议里面内容很多, 不要只考虑 json api
xfriday
301 天前
GC 类语言没有析构导致的,GC 只能回收内存,其他资源只能手动销毁

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1013181

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX