前提・実現したいこと
goでbufferedChannelを用いて繰り返し処理を書いています。
for range
を使ってchannelから値を読み込み、節内で呼び出している別の関数hoge()
で同じchannelに値を送信するようなソースコードになっています。
hoge()
が呼ばれるたびに関数内でchannelに送信する回数は減っていき、最後にはchannelへの送信自体がされなくなるような挙動のイメージです。
channelに値が送信されなくなり、ch
のバッファが空になったときにcloseをしたいのですが、適切なハンドリングができずに困っています。
恐れ入りますが、どのようにclose処理を書けばいいか(もしくは、こういった書き方はそもそも文法としてふさわしくないか)ご教示いただければと思います。
期待している出力は下記です。
stdout
13 20 31 42 50 61 70 80 9done
発生している問題・エラーメッセージ
該当のソースコード
go
1package main 2 3import ( 4 "fmt" 5 "time" 6) 7 8func main() { 9 ch := make(chan int, 10) 10 ch <- 3 11 go func() { 12 time.Sleep(2 * time.Second) // ここを適切な形に修正したい 13 close(ch) 14 }() 15 for c := range ch { 16 fmt.Println(c) 17 go hoge(ch, c) 18 } 19 fmt.Println("done") 20} 21 22func hoge(ch chan int, n int) { 23 for i := 0; i < n; i++ { 24 ch <- i 25 } 26} 27
試したこと
sync.WaitGroup
を使って、下記のように修正してみました。
うまくいく場合もあるのですが、次の繰り返しによるwg.Add(1)
より先にhoge()
内のwg.Done()
が評価されてしまうと、wg.Wait()
以降に入ってしまい、次のhogeが実行される前に終了する場合もあります。
go
1package main 2 3import ( 4 "fmt" 5 "sync" 6) 7 8func main() { 9 ch := make(chan int, 10) 10 ch <- 3 11 var wg sync.WaitGroup 12 go func() { 13 wg.Wait() 14 close(ch) 15 }() 16 for c := range ch { 17 wg.Add(1) 18 fmt.Println(c) 19 go hoge(&wg, ch, c) 20 } 21 fmt.Println("done") 22} 23 24func hoge(wg *sync.WaitGroup, ch chan int, n int) { 25 defer wg.Done() 26 for i := 0; i < n; i++ { 27 ch <- i 28 } 29} 30
補足情報(FW/ツールのバージョンなど)
回答1件
あなたの回答
tips
プレビュー