|
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.