概要
引き続き、小ネタチャネル関数の続き。( #関連記事 参照)
パイプラインを使って処理する場合、やっぱり C# の Where とか Java の filter みたいなのが欲しいところですね。
てことで、サンプルつくってみました。
サンプル
package chans // Filter -- 入力データチャネル in から取得したデータを predicate に渡して 真 となったデータを返すチャネルを生成します。 func Filter(done <-chan struct{}, in <-chan interface{}, predicate func(interface{}) bool) <-chan interface{} { out := make(chan interface{}) go func() { defer close(out) ChLoop: for { select { case <-done: break ChLoop case v, ok := <-in: if !ok { break ChLoop } if predicate(v) { select { case out <- v: case <-done: } } } } }() return out }
gomy/filter.go at master · devlights/gomy · GitHub
以下テストコードです。
package chans import ( "reflect" "strings" "testing" ) func TestFilter(t *testing.T) { type ( testin struct { input []interface{} predicate func(interface{}) bool } testout struct { result []interface{} } testcase struct { in testin out testout } ) cases := []testcase{ { in: testin{ input: []interface{}{"hello", "world"}, predicate: func(v interface{}) bool { if s, ok := v.(string); ok { if strings.HasPrefix(s, "w") { return true } return false } return false }, }, out: testout{result: []interface{}{"world"}}, }, { in: testin{ input: []interface{}{1, 2, 3, 4, 5}, predicate: func(v interface{}) bool { if i, ok := v.(int); ok { if i <= 3 { return true } return false } return false }, }, out: testout{result: []interface{}{1, 2, 3}}, }, } for caseIndex, c := range cases { func() { done := make(chan struct{}) defer close(done) inCh := make(chan interface{}) go func() { defer close(inCh) for _, v := range c.in.input { inCh <- v } }() results := make([]interface{}, 0, 0) for v := range Filter(done, inCh, c.in.predicate) { t.Logf("[test-%02d] %v", caseIndex, v) results = append(results, v) } if !reflect.DeepEqual(c.out.result, results) { t.Errorf("want: %v\tgot: %v", c.out.result, results) } }() } }
実行すると以下のようになります。
$ go test -v github.com/devlights/gomy/chans -run ^TestFilter$ === RUN TestFilter TestFilter: filter_test.go:76: [test-00] world TestFilter: filter_test.go:76: [test-01] 1 TestFilter: filter_test.go:76: [test-01] 2 TestFilter: filter_test.go:76: [test-01] 3 --- PASS: TestFilter (0.00s) PASS ok github.com/devlights/gomy/chans 0.082s
参考
- 作者:Katherine Cox-Buday
- 発売日: 2018/10/26
- メディア: 単行本(ソフトカバー)
関連記事
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場