概要
引き続き、小ネタチャネル関数の続き。( #関連記事 参照)
たまに処理をするたびに一定時間のインターバルを置いておきたいときがあったりします。
たいてい以下のように書くと思います。
for v := range Take(Repeat(1)) { // v を使って何か処理 <-time.After(100 * time.Millisecond) }
time.Sleep() 使っても同じです。で、パイプラインで以下の様にしたいって思いました。
for v := range Interval(Take(Repeat(1)), 100 * time.Millisecond) { // v を使って何か処理 }
サンプル
package chans import ( "time" ) // Interval -- 指定した間隔でデータを出力していくチャネルを生成します。 func Interval(done <-chan struct{}, in <-chan interface{}, interval time.Duration) <-chan interface{} { out := make(chan interface{}) go func() { defer close(out) for v := range OrDone(done, in) { select { case out <- v: <-time.After(interval) case <-done: } } }() return out }
gomy/interval.go at master · devlights/gomy · GitHub
以下テストコードです。
package chans import ( "testing" "time" ) func TestInterval(t *testing.T) { type ( testin struct { input []interface{} interval time.Duration } testout struct { estimation time.Duration } testcase struct { in testin out testout } ) cases := []testcase{ { in: testin{ input: []interface{}{1, 2, 3, 4, 5}, interval: 10 * time.Millisecond, }, out: testout{estimation: (10*5 + 10) * time.Millisecond}, }, { in: testin{ input: []interface{}{1, 2, 3, 4, 5}, interval: 100 * time.Millisecond, }, out: testout{estimation: (100*5 + 10) * time.Millisecond}, }, { in: testin{ input: []interface{}{1, 2, 3, 4, 5}, interval: 1000 * time.Millisecond, }, out: testout{estimation: (1000*5 + 10) * time.Millisecond}, }, } for caseIndex, c := range cases { func() { done := make(chan struct{}) defer close(done) start := time.Now() var lastElapsed time.Duration for v := range Interval(done, ForEach(done, c.in.input...), c.in.interval) { lastElapsed = time.Since(start) t.Logf("[test-%02d] %v (%v)", caseIndex, v, lastElapsed) } if c.out.estimation < lastElapsed { t.Errorf("want: <= %v\tgot: %v", c.out.estimation, lastElapsed) } }() } }
実行すると以下のようになります。
$ go test -v github.com/devlights/gomy/chans -run ^TestInterval.*$ === RUN TestInterval TestInterval: interval_test.go:56: [test-00] 1 (0s) TestInterval: interval_test.go:56: [test-00] 2 (10.1761ms) TestInterval: interval_test.go:56: [test-00] 3 (20.3089ms) TestInterval: interval_test.go:56: [test-00] 4 (30.4745ms) TestInterval: interval_test.go:56: [test-00] 5 (40.5546ms) TestInterval: interval_test.go:56: [test-01] 1 (0s) TestInterval: interval_test.go:56: [test-01] 2 (100.7949ms) TestInterval: interval_test.go:56: [test-01] 3 (200.8851ms) TestInterval: interval_test.go:56: [test-01] 4 (301.789ms) TestInterval: interval_test.go:56: [test-01] 5 (401.1778ms) TestInterval: interval_test.go:56: [test-02] 1 (0s) TestInterval: interval_test.go:56: [test-02] 2 (1.0008048s) TestInterval: interval_test.go:56: [test-02] 3 (2.0015159s) TestInterval: interval_test.go:56: [test-02] 4 (3.0022897s) TestInterval: interval_test.go:56: [test-02] 5 (4.003209s) --- PASS: TestInterval (5.56s) PASS ok github.com/devlights/gomy/chans 5.670s
ちゃんと、指定時間待機した後にデータが出力されていますね。
参考

- 作者:Katherine Cox-Buday
- 発売日: 2018/10/26
- メディア: 単行本(ソフトカバー)
関連記事
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場