1
Help us understand the problem. What are the problem?

posted at

updated at

図解 io.TeeReader(Golang)

はじめに

Goのioパッケージにはio.Readerやio.Writerのインターフェイスを有効活用するための便利なメソッドがいくつか用意されています。
自分はその中の一つであるio.TeeReaderの挙動を理解するのに手こずったので、備忘録として挙動や使い方を残しておこうと思います。

io.TeeReaderとは

io.TeeReaderメソッドは、引数で渡したio.Readerを、読み込まれた内容を2番目の引数で渡したio.Writerに書き込むio.Readerに変換するメソッドです。
自分はio.Readerを進化させるメソッドだと理解しました。イメージはこんな感じです。
スクリーンショット 2022-06-09 23.55.39.png

サンプルコード

package main

import (
	"fmt"
	"io"
	"os"
	"strings"
)

func main() {
	var r io.Reader = strings.NewReader("some io.Reader stream to be read\n")
	var w io.Writer = os.Stdout

	teeReader := io.TeeReader(r, w)

	buf := make([]byte, 1024)
	_, _ = teeReader.Read(buf)
	fmt.Println(string(buf))
}

実行結果

$ go run main.go
some io.Reader stream to be read
some io.Reader stream to be read

上記の挙動を図にすると以下のようになります。

スクリーンショット 2022-06-09 23.45.34.png

ユースケース

ユースケースとしては、クライアントからの入力を読み込むと同時にログに出力する、といったものがあるらしいです(2)。
自分は1つの画像バイナリを複数の形式にデコードしたいときに使用しました。

おわりに

ちなみにio.TeeReaderの語源はUnixコマンドのteeらしいです(2)。たしかに、↑の図を見るとデータの流れがT字になっています。

記事を書いていて気がついたのですが、自分がTeeReaderの挙動をいまいち理解できなかったのは、そもそもio.Readerのイメージが正確では無かったからだと気が付きました。io.Readerは『Readメソッドを実装する構造体』という意味なので、「読まれる」側、つまり受動者です。

しかし、自分はio.Readerを「読む」側だと無意識のうちにイメージしてしまっていたので、理解に躓いたのだと思いました。

参考

  1. Goのioパッケージのメソッドを図示
  2. Goならわかるシステムプログラミング 4刷
  3. https://pkg.go.dev/io#example-TeeReader

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?