Controle de Contexto em Go
Desenvolvedores Go discutem como usar `context` e goroutines de forma responsável, com foco em cancelamento, tempo de vida de recursos e em evitar concorrência oculta em bibliotecas. Muitos preferem APIs que pareçam síncronas, em que os chamadores controlam se o trabalho roda concorrente, embora reconheçam casos legítimos para goroutines internas e workers de longa duração. A conversa também critica `context` como uma mistura de cancelamento e dados escopados à requisição, compara isso com padrões em Rust e C#, e aborda concorrência estruturada e os limites do ideal de Go de “sem colorização async”.
Goroutines em Bibliotecas & Design de API
- Tema forte: APIs de bibliotecas devem parecer síncronas; os chamadores decidem se querem concorrência ao criar goroutines por conta própria.
- Goroutines internas são aceitáveis quando elas:
- Fazem claramente parte da abstração (por exemplo, crawler, map paralelo, pub/sub com batching, flush de métricas).
- São limitadas, bem documentadas e ajustáveis (limites, taxa, batching, caps de in-flight).
- São devidamente limpas antes de a função pública retornar (estilo de concorrência estruturada, muitas vezes via
errgroupouWaitGroup).
- Críticos de “nunca iniciar goroutines em bibliotecas” chamam isso de rígido demais; algumas cargas de trabalho são mais simples e mais seguras se a biblioteca controlar o agendamento.
- Panics em goroutines de fundo são uma preocupação: os chamadores não podem envolver isso em
recovera menos que controlem a fronteira da goroutine.
Contexto: Propósito, Padrão e Pontos de Dor
- Dois papéis principais:
- Cancelamento / deadlines / “você pode parar agora”.
- Dados escopados à requisição (logger, tracing, auth, etc.).
- Muitos não gostam do aspecto de “sacola de coisas”; é difícil saber por que uma função precisa de um context ou o que há dentro dele.
- Outros defendem parâmetros
ctxexplícitos:- Tornam visíveis a interrompibilidade e os requisitos de logging.
- Mais fáceis de revisar e raciocinar do que armazenamento implícito local de thread.
- Orientação debatida:
- Regra comum: não armazene contexts; passe-os pela pilha.
- Nuance: ok em structs que são, na prática, parâmetros, e na stdlib por compatibilidade com versões anteriores (por exemplo,
net/http), às vezes usandoNewRequestWithContext. context.WithoutCancelé visto como um compromisso útil quando se quer armazenar “valores, mas não deadlines”.
- Pontos de atrito:
- Não há como saber estaticamente se os callee respeitam o context.
- Pressão para passar
ctxpor “quase toda função”, especialmente para logging.
Contexto vs Coloração de Função / Modelos Assíncronos
- Alguns veem
ctxcomo uma leve “coloration” (funções com vs sem context), minando parcialmente a história do Go de “sem keyword async”. - Outros argumentam que isso é muito menos restritivo do que async/await:
- Você sempre pode usar
context.Background()ou envolvê-lo com timeouts. - Não cria a separação rígida sync/async vista em outras linguagens.
- Você sempre pode usar
Tratamento de Erros & Zero Values (Tópico Paralelo)
- Debate sobre o padrão
(T, error):- Um lado: valores zero/nil devem ser “úteis” mesmo quando
errorestá definido. - Outro: na maioria das APIs reais, valores zero são sem sentido ou perigosos; a falta de tipos soma força convenções desajeitadas.
- Um lado: valores zero/nil devem ser “úteis” mesmo quando