0Pricing
Go Academy · レッスン

sync.WaitGroup

複数のゴルーチンの完了を待機します。

「sync.WaitGroup」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

目的

sync.WaitGroupは、複数のゴルーチンが終了するまで待機します。メインゴルーチンがAddを呼び出してカウントを設定し、各ゴルーチンが処理の完了時にDoneを呼び出します。Waitはカウントがゼロになるまでブロックします。

基本的な使い方

各ゴルーチンを起動する前にAddを呼び出し、各ゴルーチンの最後でDoneを呼び出します(deferを使用します)。すべてのゴルーチンを起動した後にWaitを呼び出します。

var wg sync.WaitGroup
for _, item := range items {
    wg.Add(1)
    go func(v Item) {
        defer wg.Done()
        process(v)
    }(item)
}
wg.Wait()

Addはゴルーチンの開始前に実行する必要があります

wg.Add(1)はgo func()の前に呼び出し、ゴルーチンの内部では決して呼び出さないでください。そうしないと、ゴルーチンが自身を登録する前にWaitが戻る可能性があります。

よくある間違い: ループ変数のキャプチャ

すべてのゴルーチンが同じ変数を共有するのを避けるため、ループ変数はクロージャ経由ではなく、ゴルーチン関数の引数として渡します。

for _, v := range items {
    wg.Add(1)
    go func(item Item) { // correct: copy
        defer wg.Done()
        process(item)
    }(v)
}

WaitGroupの再利用

Waitが戻った後であればWaitGroupを再利用できます。ただし、以前のすべてのDone呼び出しが戻っている場合に限ります。Done呼び出しが未完了の状態で同時に再利用しないでください。

結果を扱うWaitGroup

WaitGroupは結果を収集しません。ゴルーチンの出力を集めるには、チャネルまたは(mutexと組み合わせた)スライスと併用します。

results := make([]Result, len(items))
for i, item := range items {
    wg.Add(1)
    go func(idx int, v Item) {
        defer wg.Done()
        results[idx] = process(v)
    }(i, item)
}
wg.Wait()

バッチ数を指定したAdd

ループの前に1回のAdd呼び出しへ合計数を渡すこともできます。ゴルーチンごとにAddを1回ずつ呼び出すより、わずかに効率的です。

wg.Add(len(items))
for _, item := range items {
    go func(v Item) { defer wg.Done(); process(v) }(item)
}

WaitGroupをコピーしないでください

Mutexと同様に、WaitGroupは一度使用した後にコピーしてはいけません。ポインターで渡すか、ポインターで渡す構造体に埋め込みます。

WaitGroupとerrgroupの比較

golang.org/x/sync/errgroupはWaitGroupをラップし、エラーの伝播機能を追加します。いずれかのゴルーチンの失敗時に他のゴルーチンも停止する必要がある場合は、errgroupを優先します。

contextとの組み合わせ

WaitGroupのセマンティクスと、最初のエラーでキャンセルされるcontextの両方を得るには、errgroup.WithContextを使用します。これにより、すべてのゴルーチンを適切に停止できます。

g, ctx := errgroup.WithContext(context.Background())
g.Go(func() error { return doWork(ctx) })
if err := g.Wait(); err != nil { log.Fatal(err) }

ゼロ値をそのまま使用できます

sync.WaitGroupのゼロ値はすぐに使用できます。コンストラクターは必要ありません。宣言してAddを呼び出すだけです。

確認問題

ゴルーチンを起動する前ではなく、ゴルーチンの内部でwg.Add(1)を呼び出すとどうなりますか。

まとめ: sync.WaitGroup

要点:

  • ゴルーチンを起動する前にAddを呼び出し、ゴルーチン内ではdeferを使ってDoneを呼び出します
  • Waitはカウントがゼロになるまでブロックします
  • コピーしてはいけません。ゴルーチン内でAddを呼び出してはいけません
  • エラーを伝播するにはerrgroupを使用します

よくある質問

「sync.WaitGroup」レッスンは無料ですか?

はい。「sync.WaitGroup」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「sync.WaitGroup」で何を学びますか?

複数のゴルーチンの完了を待機します。 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「sync.WaitGroup」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. sync.Mutexとsync.RWMutex
  2. sync.WaitGroup
  3. sync.Onceとsync.Map
  4. 競合検出器と安全なパターン
← Go Academyに戻る