概要
引き続き、小ネタチャネル関数の続き。( #関連記事 参照)
チャネルのパイプラインを構築するとき、諸元のデータをスライスとかで持っている場合があると
最初にそれをチャネルに流していく必要があったりします。一個ループ書けばいいだけなのですが
面倒くさいときもあります。以下な感じで処理したい。
// items はスライスで、N個のデータが入っているとする for v := range Take(ForEach(items), 10) { o <- v }
サンプル
package chans // ForEach -- 指定されたデータを出力するチャネルを生成します。 func ForEach(done <-chan struct{}, in ...interface{}) <-chan interface{} { out := make(chan interface{}) go func(data []interface{}) { defer close(out) for _, v := range data { select { case <-done: return case out <- v: } } }(in) return out }
gomy/foreach.go at master · devlights/gomy · GitHub
以下テストコードです。
package chans import ( "reflect" "testing" ) func TestForEach(t *testing.T) { type ( testin struct { input []interface{} } testout struct { output []interface{} } testcase struct { in testin out testout } ) cases := []testcase{ { in: testin{input: []interface{}{"hello", "world"}}, out: testout{output: []interface{}{"hello", "world"}}, }, } for caseIndex, c := range cases { func() { done := make(chan struct{}) defer close(done) results := make([]interface{}, 0, 0) for v := range ForEach(done, c.in.input...) { t.Logf("[test-%02d] %v", caseIndex, v) results = append(results, v) } if !reflect.DeepEqual(c.out.output, results) { t.Errorf("want: %v\tgot: %v", c.out.output, results) } }() } }
実行すると以下のようになります。
$ go test -v github.com/devlights/gomy/chans -run ^TestForEach.*$ === RUN TestForEach TestForEach: foreach_test.go:36: [test-00] hello TestForEach: foreach_test.go:36: [test-00] world --- PASS: TestForEach (0.00s) PASS ok github.com/devlights/gomy/chans 0.087s
参考
- 作者:Katherine Cox-Buday
- 発売日: 2018/10/26
- メディア: 単行本(ソフトカバー)
関連記事
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場