Da trilha de Go Este conceito ainda não saiu como card do dia. ir para o card de hoje

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.WaitGroup coordena a espera pelo término de várias goroutines.
  • Condições de corrida ocorrem quando goroutines acessam dados compartilhados sem sincronização.
  • go run -race detecta 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.
goroutines_basico.go
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")
}

Exercícios

  1. 1
    Fácil

    Iniciando uma goroutine simples

    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.

    Resolver
  2. 2
    Médio

    Contador concorrente com condição de corrida

    Crie um programa que inicie 100 goroutines, cada uma incrementando uma variável compartilhada contador 1000 vezes. Use sync.WaitGroup para esperar. Execute com go run -race e observe o aviso de condição de corrida. Depois, corrija usando sync.Mutex para proteger o incremento. O programa deve imprimir o valor final correto (100000).

    Resolver
  3. 3
    Desafio

    Pipeline concorrente com detecção de corrida

    Implemente um pipeline com três estágios: (1) gerar números de 1 a 10 em um canal; (2) dobrar cada número em goroutines separadas; (3) somar os resultados. Use sync.WaitGroup para sincronizar e go run -race para verificar ausência de data races. O resultado final deve ser a soma dos dobros (110).

    Resolver

Continue estudando