いろいろ備忘録日記

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

Goメモ-77 (シーケンスをチャネルにする, ForEach)

概要

引き続き、小ネタチャネル関数の続き。( #関連記事 参照)

チャネルのパイプラインを構築するとき、諸元のデータをスライスとかで持っている場合があると

最初にそれをチャネルに流していく必要があったりします。一個ループ書けばいいだけなのですが

面倒くさいときもあります。以下な感じで処理したい。

// 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

参考

Go言語による並行処理

Go言語による並行処理

関連記事

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com


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

  • いろいろ備忘録日記まとめ

devlights.github.io

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

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com