How to Utilize io.TeeReader in Golang

Nick Soetaert
2 min readFeb 20, 2022

--

Image by egonelbre on github

Imagine you are given some data in the form of an io.Reader, such as arbitrarily sized files or http requests. Your task is to:

  1. Send the data somewhere, such as cloud storage. (I will be using stdout.)
  2. Calculate the SHA256 hash of the data, and send it as well.

Because io.Reader represents an incoming stream of data, we can only read its contents once. A naive way to get around this is by reading the contents into a slice of bytes, any then passing this slice multiple times:

However, this implementation has the massive downside of reading everything into memory. Since this function is supposed to handle arbitrarily sized data this will simply not do; at best, you’ve created a memory hog, at worst you crash your program.

We can improve on this by using the TeeReader method which belongs to the io.Reader interface.

In short, a TeeReader is a the result of “binding” an io.Writer to an io.Reader. Reading from a TeeReader is the same as reading from your bound Reader, with the added side effect of writing all data to your bound Writer.

Go Playground link — https://play.golang.com/p/QicSg-Nrmq3

With this trivial implementation, we are now able hash and send any arbitrarily-sized data with constant memory usage. That’s the power of TeeReader!

--

--

Nick Soetaert

Software developer working with lots of IoT solar data. Follow me as I document problems I solve on the job.