概要
チャネル関数の続き。
あんまり使うことは無さそうですが、せっかく書いたのでメモメモ。
unix系のteeコマンドのように、一つの入力を2つに複製してくれるチャネルを生成する関数。
データを処理しながら、ついでに非同期で履歴出力とかする際に使えるかもしれませんね。
サンプル
package chans // Tee -- Unix の tee コマンドのように一つの入力を2つに複製するチャネルを返します。 // // noinspection GoNilness func Tee(done <-chan struct{}, in <-chan interface{}) (<-chan interface{}, <-chan interface{}) { out1 := make(chan interface{}) out2 := make(chan interface{}) go func() { defer close(out1) defer close(out2) for v := range OrDone(done, in) { var ch1, ch2 = out1, out2 for i := 0; i < 2; i++ { select { case ch1 <- v: ch1 = nil case ch2 <- v: ch2 = nil } } } }() return out1, out2 }
gomy/tee.go at master · devlights/gomy · GitHub
以下テストコードです。
package chans import ( "testing" ) func TestTee(t *testing.T) { type ( testin struct { data []interface{} } testout struct { result1 []interface{} result2 []interface{} } testcase struct { in testin out testout } ) cases := []testcase{ { in: testin{ data: []interface{}{ "hello", "world", }, }, out: testout{ result1: []interface{}{ "hello", "world", }, result2: []interface{}{ "hello", "world", }, }, }, } for _, c := range cases { func() { done := make(chan struct{}) defer close(done) inCh := make(chan interface{}, len(c.in.data)) func() { defer close(inCh) for _, v := range c.in.data { inCh <- v } }() out1, out2 := Tee(done, inCh) result1 := make([]interface{}, 0, 0) result2 := make([]interface{}, 0, 0) for v := range out1 { v2 := <-out2 t.Logf("out1: %v\tout2: %v", v, v2) result1 = append(result1, v) result2 = append(result2, v2) } if len(c.in.data) != len(result1) { t.Errorf("[len(c.in.data) != len(result1)] want: %d\tgot: %d", len(c.in.data), len(result1)) } if len(c.in.data) != len(result2) { t.Errorf("[len(c.in.data) != len(result2)] want: %d\tgot: %d", len(c.in.data), len(result2)) } if len(result1) != len(result2) { t.Errorf("[len(result1) != len(result2)] want: %d\tgot: (%d, %d)", len(c.in.data), len(result1), len(result2)) } }() } }
実行すると以下のようになります。
$ go test -v github.com/devlights/gomy/chans -run ^TestTee.*$ === RUN TestTee TestTee: tee_test.go:63: out1: hello out2: hello TestTee: tee_test.go:63: out1: world out2: world --- PASS: TestTee (0.00s) PASS ok github.com/devlights/gomy/chans 0.004s
元のチャネルから取得したデータを2つのチャネルに流しているので、2つのチャネルでちゃんと取得しないとブロックされてしまうのがネックですが、、、。
参考
- 作者:Katherine Cox-Buday
- 発売日: 2018/10/26
- メディア: 単行本(ソフトカバー)
関連記事
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場