私がしたいのは、いくつかのプロデューサー・ゴルーチン(そのうちのいくつかは完了していてもいなくてもよい)とコンシューマー・ルーチンです。問題はそのかっこ内の警告です - 回答を返す総数はわかりません。Goのプロデューサー/コンシューマーの最も慣れ親しんだイディオムは何ですか?
それでは、私がやりたいことはこれです:
package main
import (
"fmt"
"math/rand"
)
func producer(c chan int) {
// May or may not produce.
success := rand.Float32() > 0.5
if success {
c <- rand.Int()
}
}
func main() {
c := make(chan int, 10)
for i := 0; i < 10; i++ {
go producer(c, signal)
}
// If we include a close, then that's WRONG. Chan will be closed
// but a producer will try to write to it. Runtime error.
close(c)
// If we don't close, then that's WRONG. All goroutines will
// deadlock, since the range keyword will look for a close.
for num := range c {
fmt.Printf("Producer produced: %d\n", num)
}
fmt.Println("All done.")
}
だから、問題は、私はそれが間違って閉じた場合、私は近くにいない場合、である - それはまだ間違っている(コード内のコメントを参照してください)。
package main
import (
"fmt"
"math/rand"
)
func producer(c chan int, signal chan bool) {
success := rand.Float32() > 0.5
if success {
c <- rand.Int()
}
signal <- true
}
func main() {
c := make(chan int, 10)
signal := make(chan bool, 10)
for i := 0; i < 10; i++ {
go producer(c, signal)
}
// This is basically a 'join'.
num_done := 0
for num_done < 10 {
<- signal
num_done++
}
close(c)
for num := range c {
fmt.Printf("Producer produced: %d\n", num)
}
fmt.Println("All done.")
}
そして、それは完全に私が欲しいものを行います。
今、解決策は、すべてのプロデューサがに書き込むことを、アウトオブバンド信号チャネルになります!しかし私には一口のようだ。私の質問は、簡単なやり方で似たようなことをさせるイディオム/トリックはありますか?
私はここを見ていた:http://golang.org/doc/codewalk/sharemem/ をそして、それは(main
の開始時に初期化)complete
ちゃんのように思えるの範囲で使用されるが閉じられることはありません。私はどのように理解できません。
誰かが洞察力を持っているなら、私はそれを高く評価します。乾杯!
編集:fls0815には答えがあり、また、クローズレスチャンネル範囲の仕組みについての質問にも答えました。
(fls0815親切に供給された符号の前に行われる)仕事をするmodifed上記の私のコードは:
package main
import (
"fmt"
"math/rand"
"sync"
)
var wg_prod sync.WaitGroup
var wg_cons sync.WaitGroup
func producer(c chan int) {
success := rand.Float32() > 0.5
if success {
c <- rand.Int()
}
wg_prod.Done()
}
func main() {
c := make(chan int, 10)
wg_prod.Add(10)
for i := 0; i < 10; i++ {
go producer(c)
}
wg_cons.Add(1)
go func() {
for num := range c {
fmt.Printf("Producer produced: %d\n", num)
}
wg_cons.Done()
}()
wg_prod.Wait()
close(c)
wg_cons.Wait()
fmt.Println("All done.")
}
こんにちは、あなたの答えに感謝 - それは私が探していたもの確かです。 「プロデューサーだけがチャネルを閉鎖する」というあなたの提案を拡大することができますか? - それは常識/コード意識のルールのように聞こえるが、技術的な理由があるかどうか疑問に思っていた(あなたがリストしたコードサンプルにはチャンネルを閉じる主な機能があるので)。再度、感謝します! – Will
さらに詳しい情報を追加しました。 HTH。 – fls0815
ああ、そうですね。おそらく、各プロデューサーがチャンネルを閉じることが許可されているかどうかをチェックしなければならないという厳しいルールかもしれないと考えました。私たちの例ではmain()の中でそれを閉じるのではなく、はるかに厄介な(より多くの不必要な検査を伴う)ことは明らかですが、私は事をする方法であることを心配していました。私はまだスタイルのベストプラクティスを感じようとしています。 – Will