Para aguardar múltiplas goroutines finalizarem, é possível utilizar waitgroups. |
|
package main |
|
import ( "fmt" "sync" "time" ) |
|
Essa função será executada em cada goroutines. |
func worker(id int) { fmt.Printf("Worker %d starting\n", id) |
Será utilizado |
time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) } |
func main() { |
|
Este WaitGroup é usado para esperar por todas as goroutines lançadas finalizarem. Note: se um WaitGroup é explicitamente passado para uma função como parâmetro, deve ser feito com ponteiro. |
var wg sync.WaitGroup |
Inicia vãrias goroutines e incrementa o contador do WaitGroup para cada uma. |
for i := 1; i <= 5; i++ { wg.Add(1) |
Evite a utilização do mesmo valor de índice em cada goroutine closure. veja a FAQ para mais detalhes. |
i := i |
Aqui se envelopa a chamada do worker em uma closure para informar ao WaitGroup que o worker finalizou a tarefa. Desta forma o próprio worker não precisa saber da concorrência envolvendo sua execução. |
go func() { defer wg.Done() worker(i) }() } |
Bloqueado até que o contador do WaitGroup volte a 0; e que todos os workers sejam notificados que eles finalizaram. |
wg.Wait() |
Note que o código desta forma não possibilita nenhuma forma direta para propagar erros dos workers. Para mais casos avançados de uso, considere usar o pacote 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 |
|
É provável que a ordem de execução e finalização dos workers seja diferente em cada execução do código. |
Próximo exemplo: Rate Limiting.