0Pricing
Go Academy · Aula

Criando errors personalizados

errors.New, fmt.Errorf e errors sentinela

Criando errors personalizados é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Go Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Go Academy inclui 4 aulas no total.

Por que usar tipos de erro personalizados?

Os tipos de erro personalizados carregam dados estruturados além de uma mensagem de texto, permitindo que os chamadores inspecionem e reajam a condições de erro específicas:

package main
import "fmt"

// Custom error type carries extra context
type HTTPError struct {
    StatusCode int
    Message    string
}

func (e *HTTPError) Error() string {
    return fmt.Sprintf("HTTP %d: %s", e.StatusCode, e.Message)
}

func fetch(url string) error {
    return &HTTPError{404, "page not found"}
}

func main() {
    err := fetch("http://example.com")
    fmt.Println(err) // HTTP 404: page not found
}

Implementação da interface error

Qualquer tipo com um método Error() string satisfaz error:

package main
import "fmt"

type ValidationError struct {
    Field   string
    Value   interface{}
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation: field %q value %v — %s", e.Field, e.Value, e.Message)
}

func validateAge(age int) error {
    if age < 0 || age > 150 {
        return &ValidationError{"age", age, "must be between 0 and 150"}
    }
    return nil
}

func main() {
    fmt.Println(validateAge(-5))
}

Erros sentinela com errors.New

Erros sentinela são variáveis no nível do pacote para condições de erro conhecidas:

package main
import ("fmt"; "errors")

var (
    ErrNotFound      = errors.New("not found")
    ErrUnauthorized  = errors.New("unauthorized")
    ErrAlreadyExists = errors.New("already exists")
)

func getUser(id int) (string, error) {
    if id != 1 { return "", ErrNotFound }
    return "Alice", nil
}

func main() {
    _, err := getUser(99)
    if errors.Is(err, ErrNotFound) {
        fmt.Println("user does not exist")
    }
}

fmt.Errorf com %w para encapsulamento

fmt.Errorf com %w encapsula um erro, preservando o original para errors.Is e errors.As:

package main
import ("fmt"; "errors")

var ErrDatabase = errors.New("database error")

func queryDB() error {
    return fmt.Errorf("queryDB: %w", ErrDatabase)
}

func main() {
    err := queryDB()
    fmt.Println(err)                       // queryDB: database error
    fmt.Println(errors.Is(err, ErrDatabase)) // true — unwrapped
}

Erro personalizado com Unwrap

Implemente Unwrap() error no seu tipo de erro personalizado para que ele participe das cadeias de erros:

package main
import ("fmt"; "errors")

var ErrNotFound = errors.New("not found")

type QueryError struct {
    Query string
    Err   error
}

func (e *QueryError) Error() string {
    return fmt.Sprintf("query %q: %v", e.Query, e.Err)
}
func (e *QueryError) Unwrap() error { return e.Err }

func main() {
    err := &QueryError{"SELECT *", ErrNotFound}
    fmt.Println(err)
    fmt.Println(errors.Is(err, ErrNotFound)) // true
}

errors.Is — verificação de identidade

errors.Is percorre a cadeia de erros procurando um erro igual ao alvo:

package main
import ("fmt"; "errors")

var ErrTimeout = errors.New("timeout")

func deepCall() error {
    return fmt.Errorf("layer3: %w", fmt.Errorf("layer2: %w", ErrTimeout))
}

func main() {
    err := deepCall()
    fmt.Println(errors.Is(err, ErrTimeout)) // true — found deep in chain
}

errors.As — extração de tipo

errors.As encontra o primeiro erro da cadeia que corresponde a um tipo-alvo e o atribui:

package main
import ("fmt"; "errors")

type PermissionError struct{ User string }
func (e *PermissionError) Error() string { return "permission denied for " + e.User }

func action(user string) error {
    return fmt.Errorf("action: %w", &PermissionError{user})
}

func main() {
    err := action("bob")
    var pe *PermissionError
    if errors.As(err, &pe) {
        fmt.Println("denied:", pe.User) // denied: bob
    }
}

Encapsulamento de vários erros (Go 1.20+)

Go 1.20 adicionou errors.Join e fmt.Errorf com vários %w para unir erros:

package main
import ("fmt"; "errors")

func validate(name, email string) error {
    var errs []error
    if name == ""  { errs = append(errs, errors.New("name required")) }
    if email == "" { errs = append(errs, errors.New("email required")) }
    return errors.Join(errs...)
}

func main() {
    err := validate("", "")
    fmt.Println(err)
    // name required
    // email required
}

Convenções de nomenclatura de tipos de erro

Convenções para variáveis e tipos de erro em Go:

  • Variáveis de erro sentinela: ErrXxx (por exemplo, ErrNotFound)
  • Tipos de erro personalizados: XxxError (por exemplo, ValidationError)
  • Variável no nível do pacote para o sentinela, tipo ponteiro para erros ricos
  • Exportados para que os chamadores os usem em errors.Is / errors.As

Quando usar cada abordagem

Escolha a abordagem correta para cada erro:

  • errors.New — simples, sem dados extras, para verificar a identidade de um sentinela
  • fmt.Errorf — mensagem formatada com encapsulamento opcional
  • Tipo personalizado — quando o chamador precisa de dados estruturados (campos, códigos)
  • errors.Join — agrega vários erros de validação

Verificação rápida

Qual função permite extrair um tipo de erro específico de uma cadeia de erros?

Recapitulação: erros personalizados

Resumo:

  • Implemente Error() string para criar tipos de erro personalizados
  • Adicione Unwrap() error para participar das cadeias de erros
  • Use errors.Is para verificações de identidade e errors.As para extração de tipo
  • Erros sentinela: ErrXxx; tipos personalizados: XxxError
  • errors.Join agrega vários erros (Go 1.20+)

Perguntas Frequentes

A aula “Criando errors personalizados” é grátis?

Sim — o texto completo de “Criando errors personalizados” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Go Academy, atualize para CoddyKit PRO. O curso de Go Academy inclui 4 aulas no total.

O que vou aprender em “Criando errors personalizados”?

errors.New, fmt.Errorf e errors sentinela Você pratica Go Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Go Academy?

Nenhuma experiência prévia é necessária. Go Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Criando errors personalizados”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Go Academy?

Sim. Cada aula de Go Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. A interface error
  2. Criando errors personalizados
  3. Envolvendo e desembrulhando errors
  4. panic, recover e defer
← Voltar para Go Academy