ROTA · 6 CLASSES · 1 GRUPOS
Concorrência Prática: Worker Pools
Organize filas, pools, pipelines e cancelamento de trabalho concorrente.
Pré-requisitos orientam, mas nunca bloqueiam. Cinco classes fundamentais e o bônus Go 1.27 são grátis com conta.O ARCO DA ROTA
ORDEM RECOMENDADA
6 classes, do primeiro passo ao fechamento.
Cada classe leva cerca de 15–25 minutos no novo formato de slides. Você pode sair da ordem quando outro nó fizer mais sentido.
- 01Concorrência Prática: Worker PoolsGoroutines e channels: coordenação sem adivinhação
Recupere goroutines, channels e WaitGroup construindo cálculos concorrentes sem data races nem ordem acidental.
- 02Concorrência Prática: Worker PoolsChannels como fila: capacidade, fechamento e drenagem
Use channels como filas FIFO, entenda buffer e backpressure e estabeleça fechamento sem deadlocks.
- 03Concorrência Prática: Worker PoolsO worker pool: concorrência limitada e resultados ordenados
Construa um worker pool de tamanho fixo, limite recursos e devolva sucessos e erros em ordem determinística.
- 04Concorrência Prática: Worker PoolsPipelines: estágios pequenos, fechamento em cadeia
Componha fonte, filtro, transformação e fan-in com fechamento em cadeia e ordenação explícita na borda.
- 05Concorrência Prática: Worker PoolsCancelamento com context: trabalho que sabe parar
Propague context pelo pool, desbloqueie envios cancelados e teste interrupção sem depender de relógio.
- 06Concorrência Prática: Worker PoolsCapstone: processador paralelo de registros
Entregue um importador paralelo cancelável que normaliza linhas, preserva erros por registro e gera relatório auditável.
PRÉVIA DA PRIMEIRA CLASSE
Goroutines e channels: coordenação sem adivinhação
jobs := make(chan int, len(values))
for index := range values { jobs <- index } // Cada job leva o destino.
close(jobs)
results := make([]int, len(values))
var group sync.WaitGroup
group.Add(workers)
for range workers {
go func() {
defer group.Done()
for index := range jobs { results[index] = values[index] * values[index] } // Índice fixa a ordem.
}()
}
group.Wait() // Barreira antes de ler results.
Uma cozinha recebe comandas numeradas: 17, 18 e 19. Dois cozinheiros podem preparar pratos em paralelo, mas o garçom precisa entregar cada prato à mesa indicada, não à primeira mesa livre. O número da comanda é o dado que permite separar ordem de execução de ordem do resultado. Goroutines são os cozinheiros; o índice do slice é a comanda.
Iniciar uma função com go apenas autoriza execução concorrente. Não garante que ela comece antes da próxima linha, não faz main esperá-la e não protege variáveis compartilhadas. Se duas goroutines executam total += value, a operação de leitura, soma e escrita pode se intercalar: isso é uma data race, acesso concorrente incompatível ao mesmo estado.
Um channel cria um ponto de encontro. Em um channel sem buffer, o envio só termina quando algum receptor aceita o valor. close(jobs) acrescenta outro sinal: não haverá novas comandas. Workers usam range jobs e saem quando a fila foi fechada e drenada. O fechamento não espera o cálculo atual terminar, por isso o programa ainda precisa de sync.WaitGroup como barreira final.
Para resultados independentes, pré-alocamos results e fazemos cada job carregar index. Dois workers podem concluir em qualquer ordem, mas nunca escrevem na mesma posição. Para uma redução, como soma, damos um acumulador exclusivo a cada worker e combinamos as parciais somente depois de Wait. Nos dois desenhos, a sincronização segue fatos observáveis, não uma estimativa de duração.
O teste de sanidade é trocar dois por oito workers e repetir a entrada. A distribuição interna provavelmente muda; [4 9 16] e o total 29 não. Quando a API devolve o mesmo resultado sob todos os escalonamentos válidos, a concorrência deixou de vazar para o contrato.
Antes de rodar, some mentalmente os quadrados: o resultado deve ser 56, embora a ordem em que chegam a out não seja contratada. O fechamento acontece numa goroutine separada porque main precisa continuar recebendo; se chamasse group.Wait() antes do range, workers poderiam bloquear tentando enviar e ninguém os drenaria.
package main
import (
"fmt"
"sync"
)
func main() {
values := []int{2, 4, 6}
out := make(chan int)
var group sync.WaitGroup
for _, value := range values {
group.Add(1)
go func(n int) {
defer group.Done()
out <- n * n
}(value)
}
go func() {
group.Wait()
close(out)
}()
total := 0
for square := range out {
total += square
}
fmt.Println(total)
}Entre para continuar nos slides, rodar o código e enfrentar os desafios.
Começar pela rota →ESTA ROTA E TODAS AS OUTRAS
Qualquer plano abre os 192 nós.
Mensal R$19,90 · anual R$149 · lifetime R$499. Todos têm garantia de 7 dias.