Search code examples
goio

What is the difference between io.TeeReader and io.Copy?


io.TeeReader and io.Copy both read from a reader and write into a writer. What is the difference?


Solution

  • io.Copy() copies data from a source io.Reader to a destination io.Writer. And that's all. You don't get the data that was copied, it's not returned to you.

    io.TeeReader() on the other hand does not perform the copy automatically. It just returns you an io.Reader which if you read from, the data you get will also be written to the io.Writer you pass to io.TeeReader().

    io.TeeReader() is useful if you need to copy data from a reader to a writer, but you also need the data because you want to inspect it or perform calculations on it.

    For example let's say you want to copy an io.Reader to the standard output, but you also want to calculate the MD5 hash of the copied content. You may do it like this:

    s := "Hello World"
    
    r := io.TeeReader(strings.NewReader(s), os.Stdout)
    
    h := md5.New()
    if _, err := io.Copy(h, r); err != nil {
        panic(err)
    }
    
    fmt.Printf("\nHash: %x", h.Sum(nil))
    

    This will output (try it on the Go Playground):

    Hello World
    Hash: b10a8db164e0754105b7a99be72e3fe5
    

    Note that this can also be achieved using io.MultiWriter() instead of io.TeeReader():

    s := "Hello World"
    
    h := md5.New()
    mw := io.MultiWriter(h, os.Stdout)
    if _, err := io.Copy(mw, strings.NewReader(s)); err != nil {
        panic(err)
    }
    
    fmt.Printf("\nHash: %x", h.Sum(nil))
    

    This outputs the same. Try this one on the Go Playground.