いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-409 (teeコマンドのように読み出しながら別のストリームに書き込む)(io.TeeReader)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。たまに使いたいときに忘れるので、ここにメモメモ。。。

ioパッケージの下には、ある目的に特化したストリームがいろいろあります。

今回は、teeコマンドと同じような動きをしてくれる io.TeeReader について。

サンプル

package ioop

import (
    "io"
    "strings"

    "github.com/devlights/gomy/output"
)

// byteCounter は、書き込まれたバイト数を数える特殊 io.Writer です。
type byteCounter int

func (me *byteCounter) Write(p []byte) (n int, err error) {
    *me = byteCounter(int(*me) + len(p))
    return len(p), nil
}

// TeeRead は、io.TeeReader を利用したサンプルです。
//
// io.TeeReader は、teeコマンドと同じような動きをする。読み取ったデータは戻り値のReaderを経由して取得し、さらに引数で指定したio.Writerにも書き込まれる。
//
// > TeeReader returns a Reader that writes to w what it reads from r. All reads from r performed through it are matched with corresponding writes to w.
//
// > TeeReaderは、rから読み取ったものをwに書き込むReaderを返します。TeeReaderを介して実行されるrからのすべての読み取りは、対応するwへの書き込みと一致します。
//
// io.TeeReaderには、内部バッファを持っていない。
// なので、rから読み取ったデータは即時wに書き込まないとブロックされてしまう。
//
// # REFERENCES
//   - https://pkg.go.dev/io@go1.22.2#TeeReader
//   - https://cs.opensource.google/go/go/+/refs/tags/go1.22.2:src/io/io.go;l=618
func TeeRead() error {
    r := strings.NewReader("helloworld こんにちは世界")
    w := byteCounter(0)
    b, _ := io.ReadAll(io.TeeReader(r, &w))

    output.Stdoutl("[r]", string(b))
    output.StdoutHr()
    output.Stdoutl("[w]", int(w))

    return nil
}

try-golang/examples/basic/ioop/teeread.go at main · devlights/try-golang · GitHub

実行すると以下のようになります。

$ task
task: [build] go build .
task: [run] ./try-golang -onetime

ENTER EXAMPLE NAME: ioop_tee_read

[Name] "ioop_tee_read"
[r]                  helloworld こんにちは世界
--------------------------------------------------
[w]                  32


[Elapsed] 34.05µs

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。