Envolvimento de Erros com %w & errors.As
O envolvimento adiciona contexto a falhas, preservando a causa original para inspeção.
Busque em todas as páginas da documentação
O envolvimento adiciona contexto a falhas, preservando a causa original para inspeção.
fmt.Errorf com %w constrói uma cadeia de unwrap; errors.Is e errors.As percorrem essa cadeia para que os chamadores reconheçam sentinelas e tipos personalizados através de camadas intermediárias.
O Go 1.13 padronizou o envolvimento de erros: cada camada adiciona contexto de operação (ler configuração, conectar ao banco) sem destruir o os.ErrNotExist raiz ou seu tipo de domínio.
errors.As extrai dados tipados quando uma sentinela é muito genérica.
Use %v quando o erro interno não deve participar de Is/As.
Cartão de receita de referência rápida - pronto para copiar e colar.
if err != nil {
return fmt.Errorf("buscar usuário %q: %w", id, err)
}
var pathErr *os.PathError
if errors.As(err, &pathErr) {
log.Println("caminho:", pathErr.Path)
}
if errors.Is(err, os.ErrNotExist) {
return ErrNotFound
}Quando usar isso:
errors.Joinpackage main
import (
"errors"
"fmt"
"net"
"os"
)
type OpError struct {
Op string
}
func (e OpError) Error() string {
return fmt.Sprintf("%s falhou", e.Op)
}
func readDB(path string) error {
_, err := os.ReadFile(path)
if err != nil {
return OpError{Op: "leitura"}
}
return nil
}
func loadUser(path string) error {
if err := readDB(path); err != nil {
return fmt.Errorf("carregar usuário de %q: %w", path, err)
}
return nil
}
func main() {
err := loadUser("missing.db")
var op OpError
if errors.As(err, &op) {
fmt.Println("operação:", op.Op)
}
fmt.Println("não existe:", errors.Is(err, os.ErrNotExist))
fmt.Println("timeout de rede:", errors.Is(err, net.ErrClosed))
}O que isso demonstra:
OpError é alcançável através de um envolvimento fmt.Errorferrors.As requer um ponteiro para o tipo de destinoerrors.Is ainda encontra os.ErrNotExist sob OpError se a cadeia o incluirIs/As são para lógica de programa%w cria um invólucro que implementa Unwrap() error.errors.Unwrap(err) retorna um nível; Is/As iteram até encontrar uma correspondência ou nil.%w por chamada fmt.Errorf é permitido.errors.Join(errs...) (Go 1.20+) retorna um erro que pode ser desenvovido para múltiplos valores; Is/As verificam cada um.| Verbo | Cadeia de Unwrap | errors.Is / errors.As |
|---|---|---|
%w | Preserva o interno | Funciona através do envolvimento |
%v | Sem link de unwrap | O interno não é visível para Is/As |
error ou um ponteiro para um campo de struct.true e atribui o primeiro valor correspondente na cadeia.// Extração tipada
var pe *os.PathError
if errors.As(err, &pe) {
_ = pe.Path
}
// Unwrap manual de um nível (raro)
inner := errors.Unwrap(err)%w em um Errorf - Erro de compilação. Correção: Envolva uma vez por chamada; encadeie com fmt.Errorf aninhado.var target MyErr; errors.As(err, &target).errors.As para *MyErr vs MyErr deve corresponder ao que você retorna. Correção: Seja consistente; documente o tipo de retorno do construtor.errors.Is é mais simples para var ErrX. Correção: Reserve As para tipos com campos.%w mais logs verbosos podem expor tokens. Correção: Limpe mensagens; use %v em fronteiras públicas.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
Apenas errors.Is | A identidade da sentinela é suficiente | Você precisa de campos estruturados |
| Erros planos sem envolvimento | Ferramenta CLI de camada única | Serviços multi-pacote precisam de cadeias de causa |
status.Convert (gRPC) | Mapeamento de transporte RPC | Camada de domínio pura |
Unwrap []error personalizado | Agregação de múltiplos erros | Caminhos simples de falha única |
Ele envolve o argumento de erro para que o resultado implemente Unwrap e participe de errors.Is e errors.As.
errors.As percorre a cadeia de unwrap. Uma asserção de tipo apenas inspeciona o tipo dinâmico de nível superior.
fmt.Errorf("msg: %w", nil) produz um erro com unwrap nil. Evite envolver; retorne nil em caminhos de sucesso.
Não há limite rígido, mas cadeias profundas sugerem falta de logging nas fronteiras. Prefira contexto em camadas significativas.
Sim. Combine a forma do ponteiro que você retorna (*MyErr) e passe &target do tipo correto para As.
Quando várias operações falham em paralelo (validação, fan-in) e você deseja um erro retornado listando todas as causas.
Acesso de baixo nível ao erro interno imediato. A maioria do código usa Is/As em vez de loops manuais.
Sim, adicione contexto na fronteira da sua API (pacote x: operação falhou). Não faça log e envolva redundantemente sem novas informações.
Implemente Unwrap() error no seu tipo ou use fmt.Errorf com %w para comportamento padrão.
Auxiliares como os.IsNotExist usam errors.Is internamente, então eles funcionam através de cadeias %w contendo os.ErrNotExist.
Use Is para sentinelas que mapeiam para códigos de status; As ao extrair detalhes de erro para respostas JSON estruturadas.
Pequeno custo de alocação por envolvimento. Clareza e depurabilidade geralmente dominam, a menos que a análise de desempenho mostre um problema em um caminho crítico.
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