# Tratamento de Erros em Go: Padrões, Wrapping e Boas Práticas para 2026 > Guia completo sobre tratamento de erros em Go: desde a interface error até padrões avançados como wrapping, sentinel errors, errors.Is e errors.As. Domine os conceitos essenciais para entrevistas técnicas e projetos profissionais. - Published: 2026-06-15 - Updated: 2026-06-15 - Author: SharpSkill - Tags: go, error-handling, best-practices, interview, golang - Reading time: 9 min --- O tratamento de erros em Go representa uma das características mais distintivas da linguagem. Diferentemente de outras linguagens que utilizam exceções, Go adota uma abordagem explícita onde os erros são valores retornados pelas funções. Essa filosofia, embora inicialmente pareça verbosa, proporciona um controle granular sobre o fluxo de execução e facilita a criação de código robusto e previsível. Em 2026, com a consolidação do Go 1.24 e a evolução contínua do ecossistema, compreender profundamente os padrões de tratamento de erros tornou-se requisito fundamental para desenvolvedores que desejam construir aplicações escaláveis. Este artigo explora desde os fundamentos até técnicas avançadas, preparando o leitor tanto para desafios do dia a dia quanto para entrevistas técnicas. > **Dica para Entrevistas** > > O tratamento de erros em Go constitui um dos temas mais frequentes em entrevistas técnicas. Recrutadores avaliam não apenas o conhecimento da sintaxe, mas principalmente a capacidade de aplicar padrões adequados em diferentes contextos. Dominar `errors.Is`, `errors.As` e wrapping de erros demonstra maturidade técnica. ## A Interface error: Fundamento do Sistema No coração do sistema de erros de Go encontra-se uma interface extremamente simples. Essa simplicidade proposital permite que qualquer tipo que implemente o método `Error()` seja considerado um erro: ```go // builtin.go type error interface { Error() string } ``` Essa definição minimalista oferece flexibilidade extraordinária. Desenvolvedores podem criar tipos de erro personalizados que carregam informações contextuais específicas do domínio da aplicação, mantendo compatibilidade total com o ecossistema existente. ## Tipos de Erro Personalizados Quando erros simples não fornecem contexto suficiente, a criação de tipos personalizados torna-se a solução adequada. Tipos estruturados permitem incluir metadados relevantes para debugging e tratamento específico: ```go // apperror.go type NotFoundError struct { Resource string ID string } func (e *NotFoundError) Error() string { return fmt.Sprintf("%s with ID %s not found", e.Resource, e.ID) } ``` Esse padrão possibilita extrair informações do erro posteriormente, permitindo respostas HTTP adequadas ou logging estruturado. A estrutura carrega dados que seriam perdidos em uma simples string de erro. ## Sentinel Errors: Valores de Erro Predefinidos Sentinel errors representam valores de erro conhecidos e comparáveis. Definidos no nível do pacote, permitem verificações precisas em diferentes partes da aplicação: ```go // errors.go var ( ErrNotFound = errors.New("record not found") ErrUnauthorized = errors.New("unauthorized access") ErrConflict = errors.New("resource conflict") ) ``` A convenção de nomear sentinel errors com o prefixo `Err` facilita sua identificação no código. Esses valores devem ser tratados como constantes, nunca modificados após a inicialização. ## Error Wrapping: Preservando o Contexto O wrapping de erros, introduzido no Go 1.13, revolucionou o tratamento de erros na linguagem. Utilizando o verbo `%w` no `fmt.Errorf`, desenvolvedores podem adicionar contexto mantendo a cadeia de erros intacta: ```go // repository.go func (r *UserRepo) FindByID(ctx context.Context, id string) (*User, error) { user, err := r.db.QueryContext(ctx, "SELECT * FROM users WHERE id = $1", id) if err != nil { return nil, fmt.Errorf("UserRepo.FindByID(%s): %w", id, err) } return user, nil } ``` Essa técnica preserva o erro original enquanto adiciona informações sobre onde e em que contexto o erro ocorreu. O stack de chamadas fica implícito na mensagem, facilitando o debugging sem necessidade de stack traces completos. ## Verificando Erros com errors.Is A função `errors.Is` permite verificar se um erro, em qualquer ponto da cadeia de wrapping, corresponde a um valor específico. Essa função percorre toda a cadeia de erros encapsulados: ```go // handler.go func handleGetUser(w http.ResponseWriter, r *http.Request) { user, err := userService.GetByID(r.Context(), chi.URLParam(r, "id")) if errors.Is(err, ErrNotFound) { http.Error(w, "User not found", http.StatusNotFound) return } if err != nil { http.Error(w, "Internal error", http.StatusInternalServerError) return } json.NewEncoder(w).Encode(user) } ``` Mesmo que `ErrNotFound` tenha sido wrapped múltiplas vezes nas camadas inferiores, `errors.Is` consegue identificá-lo. Essa capacidade elimina a necessidade de unwrap manual e comparações frágeis de strings. ## Extraindo Tipos com errors.As Quando o objetivo é extrair um tipo específico de erro da cadeia, `errors.As` oferece a solução. Essa função tenta fazer type assertion em cada erro da cadeia até encontrar uma correspondência: ```go // middleware.go func errorMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if r := recover(); r != nil { http.Error(w, "Internal error", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } func mapErrorToHTTP(err error) int { var notFound *NotFoundError if errors.As(err, ¬Found) { return http.StatusNotFound } var validationErr *ValidationError if errors.As(err, &validationErr) { return http.StatusBadRequest } return http.StatusInternalServerError } ``` A combinação de `errors.Is` e `errors.As` proporciona um sistema robusto para tratamento de erros em aplicações complexas, permitindo decisões baseadas tanto em valores quanto em tipos. ## Erros de Domínio: Estrutura para Aplicações Complexas Em aplicações de grande porte, erros de domínio estruturados oferecem consistência e facilidade de manutenção. Um tipo de erro de domínio bem projetado inclui código, mensagem e suporte a wrapping: ```go // domain/errors.go type DomainError struct { Code string Message string Err error } func (e *DomainError) Error() string { if e.Err != nil { return fmt.Sprintf("%s: %s: %v", e.Code, e.Message, e.Err) } return fmt.Sprintf("%s: %s", e.Code, e.Message) } func (e *DomainError) Unwrap() error { return e.Err } ``` O método `Unwrap` permite que `errors.Is` e `errors.As` percorram a cadeia de erros, mantendo a compatibilidade com o sistema padrão de Go. ## Camada de Serviço: Aplicando os Padrões Na camada de serviço, os padrões de erro convergem. O código a seguir demonstra wrapping contextual combinado com erros de domínio: ```go // service/user.go func (s *UserService) Deactivate(ctx context.Context, userID string) error { user, err := s.repo.FindByID(ctx, userID) if err != nil { return fmt.Errorf("deactivating user %s: %w", userID, err) } if user.Status == StatusInactive { return &DomainError{ Code: "ALREADY_INACTIVE", Message: fmt.Sprintf("user %s is already inactive", userID), } } return s.repo.UpdateStatus(ctx, userID, StatusInactive) } ``` Essa abordagem proporciona mensagens de erro informativas para debugging enquanto mantém a capacidade de verificar tipos específicos nas camadas superiores. ## Perguntas Frequentes em Entrevistas Técnicas O tratamento de erros em Go aparece consistentemente em entrevistas para posições de backend. As perguntas mais comuns incluem: **Qual a diferença entre errors.Is e errors.As?** `errors.Is` compara valores de erro, útil para sentinel errors. `errors.As` extrai tipos específicos de erro, permitindo acesso a campos e métodos do tipo. **Quando usar tipos de erro personalizados versus sentinel errors?** Sentinel errors funcionam bem para condições simples e bem definidas. Tipos personalizados oferecem vantagens quando informações adicionais precisam ser carregadas junto ao erro. **Como implementar o método Unwrap?** O método `Unwrap() error` deve retornar o erro encapsulado, permitindo que as funções do pacote errors percorram a cadeia. ## Anti-padrões: O Que Evitar Alguns padrões de tratamento de erros prejudicam a manutenibilidade e debugging do código. O primeiro anti-padrão é ignorar erros silenciosamente: ```go // anti-pattern: silent error swallowing result, _ := riskyOperation() ``` Ignorar erros com o blank identifier dificulta a identificação de problemas em produção. Mesmo quando o erro parece irrelevante, ao menos um log deve ser registrado. Outro anti-padrão frequente é o tratamento duplo: ```go // anti-pattern: double handling if err != nil { log.Printf("operation failed: %v", err) return err } ``` Quando o erro é logado e retornado simultaneamente, a mesma falha aparece múltiplas vezes nos logs à medida que sobe pela stack de chamadas. A recomendação é logar no ponto final de tratamento ou adicionar contexto via wrapping. ## Processamento Concorrente com errgroup Para operações concorrentes, o pacote `errgroup` do módulo `golang.org/x/sync` oferece gerenciamento elegante de erros. O grupo cancela automaticamente as goroutines restantes quando uma falha ocorre: ```go // batch.go func (s *OrderService) ProcessBatch(ctx context.Context, orderIDs []string) error { g, ctx := errgroup.WithContext(ctx) g.SetLimit(10) for _, id := range orderIDs { g.Go(func() error { if err := s.processOrder(ctx, id); err != nil { return fmt.Errorf("processing order %s: %w", id, err) } return nil }) } return g.Wait() } ``` O método `SetLimit` controla o paralelismo máximo, evitando sobrecarga de recursos. O contexto derivado propaga o cancelamento automaticamente para todas as goroutines do grupo. > **Novidades do Go 1.24** > > O Go 1.24 trouxe melhorias de performance no runtime e refinamentos na biblioteca padrão. Embora o sistema de erros permaneça estável desde o Go 1.13, a comunidade continua desenvolvendo bibliotecas complementares que estendem as capacidades nativas, como suporte aprimorado a stack traces e integração com sistemas de observabilidade. ## Conclusao O tratamento de erros em Go reflete a filosofia da linguagem: explícito, simples e eficaz. Os conceitos fundamentais para dominar esse sistema incluem: - A interface `error` como base para qualquer tipo de erro personalizado - Sentinel errors para condições bem definidas e comparáveis - Tipos estruturados quando contexto adicional se faz necessário - Wrapping com `%w` para preservar a cadeia de erros - `errors.Is` para comparação de valores através da cadeia - `errors.As` para extração de tipos específicos - `errgroup` para gerenciamento de erros em operações concorrentes Evitar anti-padrões como ignorar erros ou tratá-los duplamente mantém o código limpo e os logs úteis. Em entrevistas técnicas, demonstrar compreensão desses padrões e saber quando aplicar cada um diferencia candidatos preparados. O investimento em compreender profundamente o tratamento de erros em Go retorna em forma de código mais robusto, debugging mais eficiente e maior confiança ao enfrentar desafios técnicos complexos. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/go/go-error-handling-patterns-wrapping-best-practices