[英]How to read multiple times from same io.Reader
I want to use request.Body(type io.ReadCloser)
which is containing a image.我想使用包含图像的
request.Body(type io.ReadCloser)
。
I dont want to use ioutil.ReadAll()
as i want to write this body directly to the file as well as want to decode it, so i only want to use the reference to the content to pass to further function calls,我不想使用
ioutil.ReadAll()
因为我想将此正文直接写入文件并对其进行解码,所以我只想使用对内容的引用来传递给进一步的 function 调用,
I tried creating multiple instances of reader for example shown below我尝试创建多个阅读器实例,例如如下所示
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))
}
but in second call it always results into nil
.但在第二次调用中,它总是导致
nil
。
Please help me how can i pass multiple separate reference for the same reader?请帮助我如何为同一读者传递多个单独的参考?
io.Reader
is treated like a stream. io.Reader
被视为流。 Because of this you cannot read it twice.正因为如此,你不能读两遍。 Imagine the an incoming TCP connection.
想象一下传入的 TCP 连接。 You cannot rewind the whats coming in.
你不能倒带进来的东西。
But you can use the io.TeeReader
to duplicate the stream:但是您可以使用
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))
}
Example on Go Playground Go Playground示例
Edit: As @mrclx pointed out: You need to read from the TeeReader
first, otherwise the buffer will be empty.编辑:正如@mrclx 指出的:您需要
TeeReader
读取,否则缓冲区将为空。
When you call ReadAll
it's going to empty the buffer, so the second call will always return nothing.当您调用
ReadAll
它将清空缓冲区,因此第二次调用将始终不返回任何内容。 What you could do is save the result of ReadAll
and reuse that in your functions.您可以做的是保存
ReadAll
的结果并在您的函数中重用它。 For example:例如:
bytes, _ := ioutil.ReadAll(r);
log.Println(string(bytes))
When you read from ioutil.ReadAll(r) then, the content is gone.当您从 ioutil.ReadAll(r) 读取时,内容消失了。 You can't read from it a second time.
你不能读第二遍。 For an example:
例如:
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))
Technically, on one reader, you cannot read multiple times.从技术上讲,在一个阅读器上,您不能多次阅读。
This will print twice.这将打印两次。
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并在使用缓冲区之后重要信息,否则第二个缓冲区将为空。
Clone the Reader
struct.克隆
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.