ホームページ > バックエンド開発 > Golang > 外部関数で Sync.WaitGroup のコピーを使用すると、Goroutine で出力が欠落するのはなぜですか?

外部関数で Sync.WaitGroup のコピーを使用すると、Goroutine で出力が欠落するのはなぜですか?

Mary-Kate Olsen
リリース: 2024-11-06 14:00:03
オリジナル
568 人が閲覧しました

Why does using a copy of Sync.WaitGroup in an external function lead to missing output in a goroutine?

外部関数での Sync.WaitGroup の使用

提供されたコードでは、プライマリ 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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート