[Golang] Read Twice From the Same io.Reader


This post shows how to solve the problem when you have to read twice or multiple times from the same reader (io.Reader) in Go.

Yesterday whem I was trying to write the code [1], I needed to read twice from the resp.Body reader (HTTP response body), but I always got empty result after function return. Soon I realized that the reader cannot be read more than once. Otherwise nothing is read.

I made some DuckDuckGo search, and found that io.TeeReader may be the solution to my problem. I tried to use io.TeeReader in my code, but still did not get correct result I wanted.

After some trial and error, finally I came up with my own solution: First read all bytes from the reader using ioutil.ReadAll, then use bytes.NewReader to create as many readers as we need.

The following is the example of the my own solution:

Run Code on Go Playground

package main

import (
      "bytes"
      "fmt"
      "io/ioutil"
      "strings"
)

func main() {
      originalReader := strings.NewReader("test string in test reader")

      b, err := ioutil.ReadAll(originalReader)
      if err != nil {
              panic(err)
      }

      reader1 := bytes.NewReader(b)
      b1, err := ioutil.ReadAll(reader1)
      if err != nil {
              panic(err)
      }
      fmt.Println(string(b1))

      reader2 := bytes.NewReader(b)
      b2, err := ioutil.ReadAll(reader2)
      if err != nil {
              panic(err)
      }
      fmt.Println(string(b2))
}

For realistic example, see my yesterday's post [1].


Tested on:


References:

[1](1, 2) [Golang] Auto-Detect and Convert Encoding of HTML to UTF-8
[2]golang io.reader read twice at DuckDuckGo
[3]How to write a proper tar archive in golang? : golang
[4]Speeding up Go Script to do text search : golang