[英]How to read multiple times from same io.Reader
我想使用包含图像的request.Body(type io.ReadCloser)
。
我不想使用ioutil.ReadAll()
因为我想将此正文直接写入文件并对其进行解码,所以我只想使用对内容的引用来传递给进一步的 function 调用,
我尝试创建多个阅读器实例,例如如下所示
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
a := &r
b := &r
log.Println(ioutil.ReadAll(*a))
log.Println(ioutil.ReadAll(*b))
}
但在第二次调用中,它总是导致nil
。
请帮助我如何为同一读者传递多个单独的参考?
io.Reader
被视为流。 正因为如此,你不能读两遍。 想象一下传入的 TCP 连接。 你不能倒带进来的东西。
但是您可以使用io.TeeReader
来复制流:
package main
import (
"bytes"
"io"
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
var buf bytes.Buffer
tee := io.TeeReader(r, &buf)
log.Println(ioutil.ReadAll(tee))
log.Println(ioutil.ReadAll(&buf))
}
编辑:正如@mrclx 指出的:您需要TeeReader
读取,否则缓冲区将为空。
当您调用ReadAll
它将清空缓冲区,因此第二次调用将始终不返回任何内容。 您可以做的是保存ReadAll
的结果并在您的函数中重用它。 例如:
bytes, _ := ioutil.ReadAll(r);
log.Println(string(bytes))
当您从 ioutil.ReadAll(r) 读取时,内容消失了。 你不能读第二遍。 例如:
var response *http.Response
//Read the content
rawBody, err := ioutil.ReadAll(response.Body)
if err != nil {
t.Error(err)
}
// Restore the io.ReadCloser to it's original state
response.Body = ioutil.NopCloser(bytes.NewBuffer(rawBody))
从技术上讲,在一个阅读器上,您不能多次阅读。
这将打印两次。
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
stringData, _ := ioutil.ReadAll(r)
log.Println(stringData)
log.Println(stringData)
}
@TheHippo答案是正确的我只是想添加它(但无法添加它,因为我只有49个声誉:():首先使用TeeReader并在使用缓冲区之后重要信息,否则第二个缓冲区将为空。
克隆Reader
结构。
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
v := new(strings.Reader)
*v = *r
log.Println(ioutil.ReadAll(r))
log.Println(ioutil.ReadAll(v))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.