io.MultiReader — concat Readers
r := io.MultiReader(
strings.NewReader("hello "),
strings.NewReader("world"),
)
io.Copy(os.Stdout, r)
Output
hello world
io.MultiWriter — tee to many Writers
var buf bytes.Buffer
w := io.MultiWriter(os.Stdout, &buf)
fmt.Fprintln(w, "logged")
fmt.Println("captured:", buf.String())
Output
logged
captured: logged
io.TeeReader — observe a stream as it's read
Every byte read from the returned Reader is also written to the given Writer. Great for hashing or logging as you stream.
var captured bytes.Buffer
src := strings.NewReader("hello")
r := io.TeeReader(src, &captured)
io.Copy(io.Discard, r)
fmt.Println(captured.String())
Output
hello
io.Pipe — in-memory synchronous pipe
Write in one goroutine, Read in another. Useful when an API wants a Reader but you produce bytes procedurally.
pr, pw := io.Pipe()
go func() {
defer pw.Close()
fmt.Fprint(pw, "hello")
}()
io.Copy(os.Stdout, pr)
Output
hello