Iniciando goroutines
A palavra-chave go, o ciclo de vida de goroutines e WaitGroups
Iniciando goroutines é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Go Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Go Academy inclui 4 aulas no total.
O que é uma Goroutine?
Uma goroutine é uma função leve, executada concorrentemente e gerenciada pelo ambiente de execução do Go. Goroutines são muito mais econômicas que as linhas de execução do OS — é possível executar milhares delas:
- Inicie com a palavra-chave
go - Pilha inicial de aproximadamente 2 KB (cresce dinamicamente)
- Agendadas pelo ambiente de execução do Go, não pelo OS
- Comunicam-se por canais, não por memória compartilhada
A palavra-chave go
Prefixe qualquer chamada de função com go para iniciá-la como uma goroutine:
package main
import ("fmt"; "time")
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
go greet("Alice") // runs concurrently
go greet("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond) // wait for goroutines
fmt.Println("done")
}Ciclo de vida de uma goroutine
Uma goroutine começa quando a instrução go é executada e termina quando sua função retorna. Se main retornar, todas as goroutines serão encerradas:
package main
import ("fmt"; "time")
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Duration(id) * 50 * time.Millisecond)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
go worker(i)
}
time.Sleep(300 * time.Millisecond) // naive wait
}sync.WaitGroup para coordenação
Use sync.WaitGroup em vez de uma pausa para aguardar o término das goroutines:
package main
import ("fmt"; "sync")
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // signal completion
fmt.Printf("Worker %d working\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // register one goroutine
go worker(i, &wg)
}
wg.Wait() // block until all Done()
fmt.Println("all workers finished")
}Goroutines anônimas
Inicie uma função anônima diretamente como uma goroutine — isso é útil para tarefas concorrentes incorporadas:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
i := i // capture loop variable
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("goroutine %d\n", i)
}()
}
wg.Wait()
}Armadilha da captura da variável do laço
Sem capturar a variável do laço, todas as goroutines podem ver o mesmo valor (final) — um erro clássico de concorrência em Go:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(n int) { // pass i as argument — safe
defer wg.Done()
fmt.Println(n) // prints 0, 1, 2 in some order
}(i)
}
wg.Wait()
}Goroutines e linhas de execução
Por que goroutines são preferíveis às linhas de execução do OS:
- Pilha inicial de 2 KB, em comparação com aproximadamente 1 MB nas linhas de execução do OS
- Criação leva microssegundos, em comparação com milissegundos
- O ambiente de execução do Go distribui goroutines entre linhas de execução do OS conforme GOMAXPROCS
- As trocas entre goroutines são cooperativas — sem envolvimento do núcleo
- Go cuida do agendamento; concentre-se na lógica
GOMAXPROCS
runtime.GOMAXPROCS controla quantas linhas de execução do OS executam goroutines em paralelo (por padrão, o número de CPUs):
package main
import ("fmt"; "runtime")
func main() {
// Default: number of available CPU cores
fmt.Println("CPUs:", runtime.NumCPU())
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 0 = query without changing
// Set to 1 for debugging race conditions:
// runtime.GOMAXPROCS(1)
fmt.Println("Goroutines:", runtime.NumGoroutine())
}Vazamentos de goroutines
Um vazamento de goroutine ocorre quando uma goroutine é iniciada, mas nunca termina. Causas comuns: recebimento bloqueado de um canal, bloqueio de um mecanismo de exclusão mútua ou ausência de cancelamento:
package main
import ("fmt"; "time"; "runtime")
func leaky() {
ch := make(chan int) // nobody sends to ch
go func() {
v := <-ch // blocks forever — goroutine leaked!
fmt.Println(v)
}()
}
func main() {
leaky()
time.Sleep(10 * time.Millisecond)
fmt.Println("goroutines:", runtime.NumGoroutine()) // > 1
}Boas práticas para goroutines
Diretrizes para goroutines:
- Sempre saiba como uma goroutine terminará
- Use WaitGroup ou canais para sincronizar, não uma pausa
- Passe as variáveis do laço como argumentos de função, não por meio de um fechamento
- Cancele goroutines com contexto; não as deixe em execução
- Use o detector de condições de corrida:
go run -race main.go
Verificação rápida
Qual é a maneira correta de evitar o erro de captura da variável do laço em goroutines?
Revisão: iniciando goroutines
Resumo:
- Inicie com
go fn()— leves e econômicas - Use
sync.WaitGrouppara aguardar:Add(1),defer Done(),Wait() - Capture as variáveis do laço por argumento ou redeclarando-as
- Sempre saiba como cada goroutine termina — evite vazamentos
- Use o sinalizador
-racepara detectar condições de corrida nos dados
Perguntas Frequentes
A aula “Iniciando goroutines” é grátis?
Sim — o texto completo de “Iniciando goroutines” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Go Academy, atualize para CoddyKit PRO. O curso de Go Academy inclui 4 aulas no total.
O que vou aprender em “Iniciando goroutines”?
A palavra-chave go, o ciclo de vida de goroutines e WaitGroups Você pratica Go Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Go Academy?
Nenhuma experiência prévia é necessária. Go Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Iniciando goroutines”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Go Academy?
Sim. Cada aula de Go Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Iniciando goroutines
- Canais sem buffer
- Canais com buffer
- Direção de canais e padrões de pipeline