How to read multiple times from same io.Reader

When you read from ioutil.ReadAll(r) then, the content is gone. 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))

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))

io.Reader is treated like a stream. Because of this you cannot read it twice. Imagine an incoming TCP connection - you cannot rewind what's 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.

Tags:

Go

Reader