提供されたコードでは、プライマリ goroutine がチャネルと待機グループ。ただし、場合によっては 11 番がスキップされ、出力が不完全になることがあります。
この問題は、外部関数 Print に対する sync.WaitGroup の誤った処理によって発生します。 WaitGroup のコピーを関数に渡すと、メインのゴルーチンによって待機されている元の待機グループに対して必要な Done() 呼び出しを実行できなくなります。
最良の解決策:
推奨される解決策には、次のようにコードを変更することが含まれます。
<code class="go">func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, &wg) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() } func Print(ch <-chan int, wg *sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
この修正では、Print 関数が待機グループへのポインターを受け取り、その Done() メソッドが待機グループ内で呼び出されるようにします。
代替解決策:
あるいは、チャネルを直接閉じることで、Print 関数内の WaitGroup の必要性を排除できます。すべての数値を送信した後:
<code class="go">func Print(ch <-chan int) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } }</code>
この場合、メインの goroutine は代わりにチャネルのクローズを待機する必要があります:
<code class="go">wg.Wait() close(ch)</code>
以上が外部関数で Sync.WaitGroup のコピーを使用すると、Goroutine で出力が欠落するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。