0Pricing
Go Academy · Aula

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.WaitGroup para 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 -race para 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

  1. Iniciando goroutines
  2. Canais sem buffer
  3. Canais com buffer
  4. Direção de canais e padrões de pipeline
← Voltar para Go Academy