Tipos de Erro Personalizados e Interfaces de Erro
Tipos de erro personalizados anexam dados estruturados a falhas: dicas de status HTTP, nomes de campo, sinalizadores de retentativa e códigos de erro opacos.
Busque em todas as páginas da documentação
Tipos de erro personalizados anexam dados estruturados a falhas: dicas de status HTTP, nomes de campo, sinalizadores de retentativa e códigos de erro opacos.
Projete-os para que os chamadores usem errors.As sem importar seus internos e para que você possa adicionar campos posteriormente sem quebrar o contrato de error.
A interface error requer apenas Error() string.
Tudo além disso é convenção: tipos exportados, interfaces de comportamento opcionais e wrappers não exportados que mantêm sua implementação flexível.
Erros ricos potencializam o mapeamento de API e a observabilidade; hierarquias excessivamente projetadas prejudicam a simplicidade que Go favorece.
Cartão de receita de referência rápida - pronto para copiar e colar.
type APIError struct {
Code string
Status int
Retry bool
}
func (e APIError) Error() string {
return e.Code
}
var err error = APIError{Code: "USER_MISSING", Status: 404}
var api APIError
if errors.As(err, &api) {
_ = api.Status
}Quando usar isso:
Code estáveis sem analisar stringsTimeout() bool para retentativaspackage main
import (
"errors"
"fmt"
)
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("validation: %s %s", e.Field, e.Message)
}
func (e ValidationError) HTTPStatus() int { return 422 }
func validateEmail(email string) error {
if email == "" {
return ValidationError{Field: "email", Message: "required"}
}
return nil
}
type statusCoder interface {
HTTPStatus() int
}
func writeResponse(err error) {
if err == nil {
fmt.Println("200 ok")
return
}
var sc statusCoder
if errors.As(err, &sc) {
fmt.Printf("%d %v\n", sc.HTTPStatus(), err)
return
}
fmt.Printf("500 %v\n", err)
}
func main() {
writeResponse(validateEmail(""))
}O que isso demonstra:
ValidationError é um tipo de valor com campos e uma string Error() estávelHTTPStatus() permite que os manipuladores mapeiem sem um type switch em cada varianteerrors.As extrai o tipo concreto de cadeias encapsuladas quando você adiciona %w upstreamError() string satisfaz error.errors.As(err, &target) para vincular o primeiro tipo correspondente.%w mantém os tipos descobertos através das camadas.| Escolha | Benefício | Risco |
|---|---|---|
| Struct de valor | Sem bug de interface nil tipada | Cópias na devolução (geralmente ok) |
| Struct de ponteiro | Mutação compartilhada (raro para erros) | Fácil de retornar nil tipado |
| Campo de string de código de erro | Rótulos de métricas estáveis | Precisa de enum documentado |
| Tipo wrapper opaco | Encapsulamento | Chamadores dependem de As para tipo exportado |
Bibliotecas e a biblioteca padrão usam pequenas interfaces opcionais verificadas com type assertions ou errors.As:
interface{ Timeout() bool } - decisões de retentativainterface{ Temporary() bool } - obsoleto, mas ainda visto em código mais antigointerface{ Unwrap() error } - encapsulamento (também satisfeito por erros fmt %w)Defina os seus próprios quando vários tipos de erro compartilham comportamento sem uma struct comum.
// Construtor evita vazar o layout da struct
func NewRateLimitError(retryAfter int) error {
return rateLimitError{retryAfter: retryAfter}
}
// Ruim: ponteiro nil tipado como interface de erro
func bad() error {
var p *APIError
return p // interface não nil!
}var e *MyErr; return e resulta em error não nil. Correção: Retorne nil ou use tipos de valor.Code para lógica.Is/As através do seu tipo. Correção: Implemente Unwrap() error ou incorpore o erro encapsulado.As para MyErr vs *MyErr devem corresponder às devoluções. Correção: Escolha um estilo por família de tipos.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Variáveis sentinela | Único resultado fixo | Precisa de campos ou metadados |
Apenas fmt.Errorf | Ferramentas internas rápidas | Manipulação programática estável necessária |
status.Status gRPC | Apenas transporte gRPC | A camada de domínio deve permanecer agnóstica ao transporte |
errors.Join | Múltiplas falhas em nível de campo | Falha única com uma causa raiz |
Quando os chamadores precisam de campos (status, nome do campo, retentativa) ou interfaces de comportamento além da identidade sim/não.
Exporte tipos que fazem parte do seu contrato. Mantenha os erros de implementação interna não exportados com construtores.
Uma mensagem concisa e humana, muitas vezes incluindo um código estável. A lógica do programa deve usar campos via errors.As, não análise de strings.
Defina pequenos métodos (HTTPStatus() int). Os manipuladores usam errors.As para o tipo de interface para chamá-los sem listar cada struct.
Prefira receptores de valor para structs de erro, a menos que você tenha um motivo específico para ponteiros. Valores evitam armadilhas de nil tipado.
Sim. Retorne o erro encapsulado para que Is/As atravessem seu tipo.
Adicione campos sem remover os exportados. Prefira novos códigos em um campo de string em vez de renomear tipos.
Discutível. Uma abordagem pragmática: HTTPStatus() opcional em tipos de camada de aplicativo; mantenha os pacotes de domínio agnósticos ao transporte quando reutilizados entre CLI e HTTP.
Retorne errors.Join de vários valores ValidationError quando vários campos falharem simultaneamente.
Raramente necessário. Interfaces e As cobrem a maioria dos casos; tipos de resultado genéricos (T, error) são mais comuns.
Avançado: implemente Format para saída detalhada %+v (usada por algumas bibliotecas de log). Opcional para diagnósticos de aplicativos.
Use errors.As em testes para afirmar campos. Evite comparar strings Error() completas quando as mensagens evoluem.
Versões de Stack: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, 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: 19 de jul. de 2026