あなたの monitorWorker は死ぬことはありません。すべてのワーカーが終了すると、cs を待ち続けます。このデッドロックは、cs で他に何も送信されないため、wg が 0 に到達しないためです。考えられる修正は、すべてのワーカーが終了したときにモニターがチャネルを閉じることです。for ループが main にある場合は、ループを終了し、main から戻り、プログラムを終了します。
例: http://play.golang.org/p/nai7XtTMfr
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, cs chan string, i int) {
defer wg.Done()
cs <- "worker" + strconv.Itoa(i)
}
func monitorWorker(wg *sync.WaitGroup, cs chan string) {
wg.Wait()
close(cs)
}
func main() {
wg := &sync.WaitGroup{}
cs := make(chan string)
for i := 0; i < 10; i++ {
wg.Add(1)
go worker(wg, cs, i)
}
go monitorWorker(wg, cs)
for i := range cs {
fmt.Println(i)
}
}
編集:これは、OP の最初のコメントに対する回答です。
プログラムには、同期が必要な 3 つの部分があります。まず、すべてのワーカーがデータを送信する必要があります。次に、印刷ループでそのデータを印刷する必要があります。次に、メイン関数が戻る必要があり、それによってプログラムが終了します。あなたの例では、すべてのワーカーがデータを送信し、すべてのデータが出力されますが、正常に返される必要があるというメッセージがメインに送信されることはありません。
私の例では、メインが印刷を行い、「monitorWorker」は、印刷する必要があるすべてのデータを受信したときにメインに通知するだけです。このようにして、プログラムはデッドロックではなく正常に終了します。
印刷ループが別のゴルーチンにあると主張する場合は、それを行うことができます。ただし、追加の通信をメインに送信して返す必要があります。この次の例では、チャネルを使用して、すべてのデータが印刷されたときにメイン エンドを確保します。
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, cs chan string, i int) {
defer wg.Done()
cs <- "worker" + strconv.Itoa(i)
}
func monitorWorker(wg *sync.WaitGroup, cs chan string) {
wg.Wait()
close(cs)
}
func printWorker(cs <-chan string, done chan<- bool) {
for i := range cs {
fmt.Println(i)
}
done <- true
}
func main() {
wg := &sync.WaitGroup{}
cs := make(chan string)
for i := 0; i < 10; i++ {
wg.Add(1)
go worker(wg, cs, i)
}
go monitorWorker(wg, cs)
done := make(chan bool, 1)
go printWorker(cs, done)
<-done
}