Erros como Valores: A Filosofia de Erros do Go
O Go rejeita exceções para caminhos de falha esperados.
Busque em todas as páginas da documentação
O Go rejeita exceções para caminhos de falha esperados.
Em vez disso, as funções retornam um valor error ao lado de seu resultado normal, e os chamadores decidem imediatamente se devem propagar, encapsular, registrar ou traduzir essa falha.
Essa escolha molda a legibilidade, as fronteiras da biblioteca e como os serviços de produção mapeiam problemas de domínio para respostas HTTP ou gRPC.
error retornado como qualquer outro resultado - não um mecanismo de controle de fluxo que desenrola a pilha.catch ocultos.error, erros sentinela, encapsulamento com %w, errors.Is / errors.As, panic vs error, fail-fast nas fronteiras.if err != nil adicionam verbosidade; pilhas de chamadas profundas exigem encapsulamento disciplinado; não há retentativa ou classificação embutida, a menos que você a projete.Antes do Go 1, os designers observaram grandes bases de código C++ e Java lutando com exceções usadas tanto para falhas esperadas quanto catastróficas.
O fluxo de controle oculto tornava difícil saber quais funções poderiam falhar, e os blocos catch distantes da causa obscureciam a remediação.
A resposta do Go é a simplicidade mecânica: uma assinatura de função diz tudo.
func ReadConfig(path string) (Config, error)Se o segundo retorno não for nil, o primeiro valor geralmente é inutilizável.
Não há try, finally, nem desenrolar implícito da pilha para problemas comuns.
A interface error é intencionalmente minúscula:
type error interface {
Error() string
}Qualquer coisa com um método string a satisfaz - variáveis sentinela, mensagens formatadas, structs ricas com campos extras.
Erros como valores significa que você os passa como int ou string: armazene-os, compare-os com errors.Is, inspecione tipos com errors.As e anexe contexto com fmt.Errorf("load config: %w", err).
panic existe, mas o Go idiomático o reserva para violações de invariantes e erros de programador (desreferenciamento de ponteiro nulo, índice fora do intervalo).
Bibliotecas não devem entrar em pânico com entrada de usuário inválida; aplicativos podem optar por travar em caso de má configuração na inicialização.
O modelo de erro interage com outras escolhas explícitas do Go: múltiplos valores de retorno, sem herança e APIs em nível de pacote.
Um pacote de baixo nível como os exporta erros sentinela (os.ErrNotExist) e encapsuladores específicos da operação.
Middleware e manipuladores ficam nas fronteiras - manipuladores HTTP, interceptadores gRPC, CLI main - onde os erros se tornam códigos de status, códigos de saída ou campos de log estruturados.
Entre essas camadas, o código geralmente encapsula erros para adicionar contexto enquanto preserva a causa raiz para errors.Is e errors.As.
chamador ──chama──> biblioteca ──retorna──> (T, error)
│ │
│ se err != nil │
├─ encapsula com %w ───────────────────┘
├─ registra + retorna
└─ mapeia para resposta do cliente na fronteira
O encapsulamento (Go 1.13+) armazena uma cadeia de desenrolamento.
errors.Is(err, target) percorre essa cadeia para igualdade sentinela.
errors.As(err, &target) encontra o primeiro valor de erro atribuível a um tipo de ponteiro.
Isso substitui a correspondência de strings frágil e as asserções de tipo em todas as camadas.
Bibliotecas devem retornar erros estáveis e documentados; aplicativos não devem vazar erros brutos do os para clientes externos sem tradução.
O pacote context adiciona cancelamento (context.Canceled, context.DeadlineExceeded) como erros de primeira classe que se propagam pelo mesmo padrão (T, error).
Em escala, as equipes adotam políticas de erro: convenções de nomenclatura (Err prefixo para sentinelas), se devem exportar tipos de erro e quando usar %w vs %v (encapsular vs substituir cadeia).
| Abordagem | Força | Fraqueza | Melhor Ajuste |
|---|---|---|---|
Sentinela var ErrX = errors.New(...) | Verificações simples de errors.Is | Torna-se difícil de gerenciar com muitas variantes | Pequenos vocabulários de domínio |
| Tipos de struct personalizados | Campos ricos (código HTTP, retentável) | Chamadores devem usar errors.As | Fronteiras de serviço, SDKs |
Erros opacos + Unwrap | API pública estável | Menos inspecionável para chamadores | Bibliotecas públicas |
panic + recover | Para a goroutine em caso de quebra de invariante | Fácil de usar incorretamente nas bordas da API | Middleware HTTP, motores de template |
Hooks de observabilidade geralmente residem em tipos personalizados: Retryable() bool, LogLevel() slog.Level, ou detalhes de status gRPC.
Go 1.20+ errors.Join mescla múltiplas falhas (útil em validação e fan-in paralelo).
Para código concorrente, os erros ainda retornam em canais ou através de errgroup; a filosofia de valores não muda, apenas o caminho de agregação.
Segurança: encapsular entrada do usuário em strings de erro pode vazar detalhes internos; mapeie para mensagens de cliente seguras na camada mais externa.
err é um bug, e linters sinalizam erros não verificados.if err != nil significa que o tratamento de erros do Go é fraco - A verbosidade compra raciocínio local; o encapsulamento e errors.Is/As fornecem inspeção estruturada sem uma hierarquia de exceções paralela.panic quebra os contratos do chamador; retorne error para que ferramentas CLI, servidores e testes possam recuperar ou relatar de forma limpa.err == io.EOF sempre funciona - Erros encapsulados falham na igualdade direta; use errors.Is(err, io.EOF).%w - Use %v quando a causa interna não deve ser visível para Is/As (fronteiras de segurança ou abstração).Uma interface de método único (Error() string). Tipos concretos a implementam para representar falha sem uma hierarquia de classes.
Eles queriam que a falha fosse visível nas assinaturas de função e tratada localmente, evitando fluxo de controle oculto e blocos catch distantes que obscurecem o fluxo de dados em bases de código grandes.
Somente quando a operação foi bem-sucedida. Nunca retorne um ponteiro nil tipado como um valor de interface error - use var err error ou retorne um nil não tipado.
Superficialmente, mas o Go idiomático limita panic a erros irrecuperáveis do programador. Falhas esperadas usam o retorno error.
fmt.Errorf("contexto: %w", err) adiciona uma mensagem e preserva a cadeia para errors.Is e errors.As. Chamadores podem corresponder sentinelas ou tipos através de encapsulamentos.
Exporte um pequeno conjunto estável. Prefira sentinelas ou tipos documentados para erros de contrato; mantenha detalhes internos não exportados ou opacos.
Muitas vezes uma vez na fronteira (manipulador HTTP, loop de worker) após encapsular upstream. Registrar em todas as camadas duplica o ruído, a menos que cada camada adicione contexto distinto.
context.Context retorna context.Canceled ou context.DeadlineExceeded. Propague com %w para que os chamadores diferenciem timeout de falha de I/O.
Evite isso. Use errors.Is para casos esperados (por exemplo, io.EOF), não para ramificações rotineiras através de muitas camadas.
errors.Join (Go 1.20+) agrega múltiplos erros em um único valor que pode ser desenrolado para cada constituinte. Útil quando várias validações falham em paralelo.
A alocação de valores de erro tem um custo pequeno. Caminhos quentes às vezes usam retornos sentinela sem formatação, mas a clareza geralmente supera micro-otimizações, a menos que os perfis provem o contrário.
Camadas de domínio retornam error; camadas de transporte as mapeiam para códigos de status e corpos JSON estáveis. Veja o artigo de design de erro de API para padrões concretos.
Versões de Stack: Esta página foi escrita para Go 1.26.x (padrão Green Tea GC, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026