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 sentinelafmt.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() stringpara criar tipos de erro personalizados - Adicione
Unwrap() errorpara participar das cadeias de erros - Use
errors.Ispara verificações de identidade eerrors.Aspara extração de tipo - Erros sentinela:
ErrXxx; tipos personalizados:XxxError errors.Joinagrega 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
- A interface error
- Criando errors personalizados
- Envolvendo e desembrulhando errors
- panic, recover e defer