Da trilha de Go Este conceito ainda não saiu como card do dia. ir para o card de hoje

Go Erros Intermediário

Erros customizados

Em Go, erros são valores que implementam a interface error. Você pode criar erros customizados definindo tipos que implementam Error() string ou usando errors.New e fmt.Errorf. Isso permite transportar informações extras além da mensagem, como códigos de status ou campos específicos.

Erros sentinela são valores de erro pré-definidos (como io.EOF) usados para comparação com errors.Is. Já errors.Join combina múltiplos erros em um só, útil quando várias operações falham independentemente.

Escolha entre eles conforme a necessidade: use erros sentinela para condições simples e bem conhecidas; tipos customizados quando precisar de dados adicionais; e errors.Join para agregar falhas sem perder informações.

Pontos-chave

  • Erros customizados são tipos que implementam a interface error com o método Error() string.
  • Erros sentinela são valores como io.EOF e devem ser comparados com errors.Is.
  • errors.Join agrega múltiplos erros em um único erro que pode ser desmembrado com errors.Unwrap.
  • Use fmt.Errorf com %w para envolver erros e preservar a cadeia para errors.Is e errors.As.
  • Escolha o tipo de erro conforme a necessidade: sentinela para comparação simples, customizado para dados extras, Join para múltiplas falhas.
custom_errors.go
package main

import (
	"errors"
	"fmt"
)

// ValidationError é um erro customizado com campo extra.
type ValidationError struct {
	Field string
	Msg   string
}

func (e *ValidationError) Error() string {
	return fmt.Sprintf("campo %q: %s", e.Field, e.Msg)
}

// ErrNotFound é um erro sentinela.
var ErrNotFound = errors.New("recurso não encontrado")

func buscar(id int) error {
	if id != 1 {
		return fmt.Errorf("buscar id=%d: %w", id, ErrNotFound)
	}
	return nil
}

func validar(nome string) error {
	if nome == "" {
		return &ValidationError{Field: "nome", Msg: "não pode ser vazio"}
	}
	return nil
}

func main() {
	// Erro customizado
	err := validar("")
	var ve *ValidationError
	if errors.As(err, &ve) {
		fmt.Println("Validação falhou no campo:", ve.Field)
	}

	// Erro sentinela com wrapping
	err = buscar(2)
	if errors.Is(err, ErrNotFound) {
		fmt.Println("Não encontrado:", err)
	}

	// errors.Join
	err1 := validar("")
	err2 := buscar(3)
	joined := errors.Join(err1, err2)
	fmt.Println("Erros combinados:")
	fmt.Println(joined)
}

Exercícios

  1. 1
    Fácil

    Erro sentinela para divisão por zero

    Crie um erro sentinela ErrDivisaoPorZero e uma função dividir(a, b float64) (float64, error) que retorna esse erro quando b for zero. No main, chame a função com b=0 e verifique o erro com errors.Is.

    Resolver
  2. 2
    Médio

    Erro customizado com código de status

    Crie um tipo HTTPError que implementa error e contém os campos Status int e Message string. A função requisitar(url string) error retorna um *HTTPError com status 404 se a URL for "/nao-existe". No main, use errors.As para extrair o *HTTPError e imprimir o status e a mensagem.

    Resolver
  3. 3
    Desafio

    Agregando erros com errors.Join

    Crie uma função validarUsuario(nome, email string) error que valida nome e email. Se ambos forem inválidos, retorne um erro combinado usando errors.Join. Defina erros sentinela ErrNomeVazio e ErrEmailInvalido. No main, chame a função com dados inválidos, verifique com errors.Is se ambos os erros estão presentes e imprima a mensagem combinada.

    Resolver

Continue estudando