Fácil Go

Iniciando uma goroutine simples

Enunciado

Escreva um programa que inicie uma goroutine para imprimir "Olá da goroutine!" e, em seguida, imprima "Olá da main!" na função principal. Use sync.WaitGroup para garantir que a goroutine termine antes do programa encerrar.

Requisitos

  • Usar go func() para iniciar a goroutine.
  • Usar sync.WaitGroup com Add(1), Done() e Wait().
  • A saída deve conter as duas mensagens, em qualquer ordem, mas a main deve esperar.

Código inicial

package main

import (
	"fmt"
	"sync"
)

func main() {
	// TODO: criar WaitGroup, iniciar goroutine e esperar
}

Saída esperada

Olá da goroutine!
Olá da main!
Ver dica

Lembre-se de chamar wg.Add(1) antes de iniciar a goroutine e wg.Done() dentro dela (pode usar defer).

Mostrar solução
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup

	wg.Add(1) // registra uma goroutine
	go func() {
		defer wg.Done() // decrementa o contador ao terminar
		fmt.Println("Olá da goroutine!")
	}()

	wg.Wait() // espera a goroutine terminar
	fmt.Println("Olá da main!")
}

Passo a passo

  1. Declaramos var wg sync.WaitGroup para coordenar a execução.
  2. wg.Add(1) informa que uma nova goroutine será executada.
  3. go func() { ... }() inicia a goroutine anônima imediatamente.
  4. Dentro da goroutine, defer wg.Done() garante que o contador seja decrementado ao final, mesmo se ocorrer um panic.
  5. A goroutine imprime a mensagem.
  6. wg.Wait() bloqueia a main até que o contador chegue a zero.
  7. Por fim, a main imprime sua mensagem.

Por que funciona

WaitGroup é um contador seguro para concorrência. Add(1) aumenta o contador, Done() diminui e Wait() bloqueia até que ele seja zero. Assim, a main não termina antes da goroutine, evitando que o programa encerre prematuramente.

Erros comuns

  • Esquecer wg.Add(1): wg.Wait() retorna imediatamente e a goroutine pode não rodar. Corrija chamando Add antes do go.
  • Chamar wg.Done() fora da goroutine: pode decrementar antes da hora. Use defer dentro da função.
  • Copiar o WaitGroup (ex.: passar por valor): causa comportamento indefinido. Sempre passe por ponteiro ou use a variável original.

Outra forma de resolver

Usar um canal para sincronizar:

done := make(chan struct{})
go func() {
    fmt.Println("Olá da goroutine!")
    close(done)
}()
<-done
fmt.Println("Olá da main!")

Canais são preferíveis quando há troca de dados, não apenas sincronização.

Saída esperada

Olá da goroutine!
Olá da main!