问题
I want to use request.Body(type io.ReadCloser)
which is containing a image.
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,
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
.
Please help me how can i pass multiple separate reference for the same reader?
回答1:
io.Reader is treated like a stream. Because of this you cannot read it twice. Imagine the an incoming TCP connection. You cannot rewind the whats coming in.
But you can use the io.TeeReader to duplicate the stream:
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
Edit: As @mrclx pointed out: You need to read from the TeeReader
first, otherwise the buffer will be empty.
回答2:
When you call ReadAll
it's going to empty the buffer, so the second call will always return nothing. What you could do is save the result of ReadAll
and reuse that in your functions. For example:
bytes, _ := ioutil.ReadAll(r);
log.Println(string(bytes))
回答3:
Technically, on one reader, you cannot read multiple times.
- Even if you create different references but
- when you read once it will be same object referred by all references.
- so what you can do is read the content and store it in one variable.
- Then use that variable as many times as you want.
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)
}
回答4:
@TheHippo answer is correct I just wanted to add this (but couldn't add it because I have only 49 reputation:( ): it's important that you use the TeeReader first and after you use the buffer where the info is copied otherwise the second buffer will be empty.
来源:https://stackoverflow.com/questions/39791021/how-to-read-multiple-times-from-same-io-reader