複数のゴルーチンの完了を待つために、WaitGroup を使うことができます。 |
|
package main |
|
import ( "fmt" "sync" "time" ) |
|
これは、すべてのゴルーチンで実行する関数です。 |
func worker(id int) { fmt.Printf("Worker %d starting\n", id) |
時間のかかるタスクをシミュレートするためにスリープします。 |
time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) } |
func main() { |
|
この WaitGroup は、ここで起動したすべてのゴルーチンが完了するのを 待つために使われます。WaitGroup を関数に引数として渡す場合は、 ポインタで 渡す必要がある点に注意してください。 |
var wg sync.WaitGroup |
いくつかのゴルーチンを起動し、そのたびに WaitGroup のカウンターを インクリメントします。 |
for i := 1; i <= 5; i++ { wg.Add(1) |
ゴルーチンのクロージャで同じ |
i := i |
クロージャでワーカー呼び出しをラップし、ワーカーが完了したことを WaitGroup に伝えます。こうすると、ワーカー自身は並行処理のことを 意識する必要がなくなります。 |
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 |
|
ワーカーが起動および終了する順序は、実行するたびに変わりえます。 |
Next example: Rate Limiting.