例による Go: WaitGroups

複数の goroutine の終了を待機するには、wait group を使用できます。

package main
import (
    "fmt"
    "sync"
    "time"
)

各 goroutine で実行する関数は次のとおりです。

func worker(id int) {
    fmt.Printf("Worker %d starting\n", id)

高コストのタスクをシミュレートするためにスリープです。

    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}
func main() {

この wait group は、ここで起動したすべての goroutine の終了を待機するために使用します。注: wait group が明示的に関数に渡される場合、ポインターとして渡される必要があります。

    var wg sync.WaitGroup

複数の goroutine を起動し、それぞれに対して wait group カウンターを増分します。

    for i := 1; i <= 5; i++ {
        wg.Add(1)

ワーカー呼び出しをクロージャでラップし、このワーカーが完了したことを確実に wait group に通知します。こうすることで、ワーカー自身が実行に関わる並行プリミティブを認識する必要がなくなります。

        go func() {
            defer wg.Done()
            worker(i)
        }()
    }

WaitGroup カウンターが 0 に戻るまでブロックします。すべてのワーカーが完了したことを通知しています。

    wg.Wait()

このアプローチではワーカーからエラーを伝達する明確な方法がないことに注意してください。より高度な使用例の場合は、errgroup パッケージの使用を検討してください。

}
$ go run waitgroups.go
Worker 5 starting
Worker 3 starting
Worker 4 starting
Worker 1 starting
Worker 2 starting
Worker 4 done
Worker 1 done
Worker 2 done
Worker 5 done
Worker 3 done

ワーカーの起動と終了の順序は、呼び出しごとに異なる可能性があります

次の例: 速度制限