go - 如何保存,然后再次提供 io.Reader 类型的数据?
问题描述
我想用gocal
通过 HTTP 调用检索到的数据解析几次。由于我想避免对每个解析进行调用,我想保存这些数据并重用它。
Body
我得到的http.Get
类型是io.ReadCloser
. gocal
解析器需要它io.Reader
才能工作。
由于我只能检索Body
一次,因此可以将其保存,body, _ := io.ReadAll(get.Body)
但后来我不知道如何[]byte
作为io.Reader
返回(对gocal
解析器,多次以考虑不同的解析条件)
解决方案
正如您所想的那样,它http.Response.Body
被公开为io.Reader
,这个阅读器不可重用,因为它直接连接到底层连接*(可能是tcp / utp / 或任何其他流,如net包下的阅读器)。一旦您从连接中读取字节,新字节就会等待另一次读取。
实际上,为了保存响应,您需要先将其排空,然后将结果保存在变量中。
body, _ := io.ReadAll(get.Body)
为了使用 Go 编程语言多次重复使用该字节片,标准 API 提供了缓冲读取器bytes.NewReader
。
该缓冲区充分提供了Reset([]byte)
重置缓冲区状态的方法。
这bytes.Reader.Reset
对于在没有分配的情况下多次读取相同的字节缓冲区非常有用。相比之下,bytes.NewReader
每次调用时都会分配。
最后,在两次连续调用之间c.Parser
,您应该使用之前收集的字节缓冲区重置缓冲区。
如 :
buf := bytes.NewReader(body)
// initialize the parser
c.Parse()
// process the result
// reset the buf, parse again
buf.Reset(body)
c.Parse()
你可以试试这个版本https://play.golang.org/p/YaVtCTZHZEP它使用了strings.NewReader
缓冲区,但是界面和行为都差不多。
- 不是很明显,这是一般原则,传输读取标题,并且除非您使用它,否则不要触及正文。另见。
推荐阅读
- javascript - 无法使用 innerHTML 和 innerText 更改标签内容
- angular - 为 Firestore 创建的每个用户的自定义 UID
- django - 否则在 django 中不起作用,我不知道如何解决这个问题
- c++ - C++ 赋值复合运算符与简单运算符结合赋值运算符
- javascript - 在 Svelte 动作上传递多个参数
- typescript - Typescript 接口属性作为通用对象的嵌套键
- php - PHP 访问私有 Azure 存储容器
- javascript - FullCalendar eventDrop 在几天之间不起作用
- java - NetBeans 找不到包 java.lang
- java - 为什么这个 java.lang.NullPointerException 错误?