Go Concorrência Intermediário
Goroutines
Em Go, uma goroutine é uma linha de execução leve gerenciada pelo runtime. Para iniciar uma, basta usar a palavra-chave go antes de uma chamada de função: go minhaFuncao(). O runtime multiplexa milhares de goroutines sobre um número menor de threads do sistema operacional, tornando a concorrência simples e eficiente.
Como goroutines rodam de forma independente, o programa principal pode terminar antes delas. Para esperar que todas concluam, usamos sync.WaitGroup: incrementamos com wg.Add(1), decrementamos com wg.Done() (normalmente via defer) e bloqueamos com wg.Wait().
Quando duas ou mais goroutines acessam a mesma variável sem sincronização, ocorre uma condição de corrida (data race). O resultado pode ser imprevisível. O comando go run -race instrumenta o programa e detecta essas condições em tempo de execução, mostrando um relatório detalhado.
Neste card, vamos criar goroutines, sincronizá-las com WaitGroup e demonstrar como identificar e corrigir uma condição de corrida usando sync.Mutex (ou canais, em exemplos futuros).
Pontos-chave
go func()inicia uma goroutine que executa concorrentemente com a função principal.sync.WaitGroupcoordena a espera pelo término de várias goroutines.- Condições de corrida ocorrem quando goroutines acessam dados compartilhados sem sincronização.
go run -racedetecta data races durante a execução e ajuda a depurar concorrência.- Use
defer wg.Done()para garantir a decrementação mesmo em caso de erro.
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // registra que uma nova goroutine vai rodar
go func(id int) {
defer wg.Done() // garante que o contador será decrementado
fmt.Printf("Goroutine %d executando\n", id)
}(i)
}
wg.Wait() // espera todas as goroutines terminarem
fmt.Println("Todas as goroutines concluídas")
}