"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Erros personalizados no Go

Erros personalizados no Go

Publicado em 2024-11-08
Navegar:830

Custom errors in Go

Introdução

Golang ou Go possui um mecanismo robusto de tratamento de erros que é parte integrante do design da linguagem. Embora Go forneça tipos de erro integrados, há situações em que você pode precisar de mais controle e contexto no tratamento de erros.
É aqui que entra em jogo a criação de erros personalizados. Erros personalizados podem fornecer mensagens de erro mais informativas e podem ser usados ​​para categorizar diferentes tipos de erros em seu aplicativo.

Neste artigo, exploraremos como criar e usar erros personalizados em Golang de maneira eficaz.

Compreendendo o tratamento de erros integrado do Go

No Go, o tipo de erro é uma interface integrada semelhante a esta:

type error interface {
    Error() string
}

Qualquer tipo que implemente o método Error() com um tipo de retorno string satisfaz esta interface e pode ser considerado um erro. Isso é simples, mas poderoso porque permite criar tipos de erro personalizados simplesmente implementando esse método.

Tratamento básico de erros em Go

Aqui está um exemplo rápido de tratamento básico de erros em Go:

package main

import (
    "errors"
    "fmt"
)

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
    }
}

func doSomething() error {
    return errors.New("something went wrong")
}

Este exemplo usa a função erros.New para criar um erro básico. Embora seja útil para casos simples, falta-lhe a capacidade de fornecer mais contexto ou de distinguir entre diferentes tipos de erros.

Por que criar erros personalizados?

Erros personalizados são essenciais quando você precisa de mensagens de erro mais descritivas ou quando deseja lidar com diferentes tipos de erros de maneira diferente. Por exemplo, talvez você queira retornar um tipo de erro específico quando um arquivo não for encontrado e outro tipo quando um arquivo estiver corrompido. Erros personalizados também podem conter dados adicionais, facilitando a depuração e fornecendo informações mais detalhadas ao chamador.

Criando erros personalizados no Go

Para criar um erro personalizado em Go, você define um novo tipo que implementa o método Error(). Vejamos um exemplo.

Exemplo 1: um erro personalizado simples

Veja como você pode criar um erro personalizado simples:

package main

import (
    "fmt"
)

type MyError struct {
    Code    int
    Message string
}

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

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
    }
}

func doSomething() error {
    return &MyError{
        Code:    404,
        Message: "Resource not found",
    }
}

Neste exemplo, MyError é um tipo de erro personalizado que inclui um código e uma mensagem. O método Error() os formata em uma string, facilitando a impressão ou registro do erro.

Exemplo 2: Verificando erros com a função erros.Is

Às vezes, é útil comparar os erros diretamente. É aqui que entram os erros sentinela. Um erro sentinela é uma variável predefinida e exportada que representa um erro específico.

package main

import (
    "errors"
    "fmt"
)

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

func main() {
    err := doSomething()
    if errors.Is(err, ErrNotFound) {
        fmt.Println("Error:", err)
    }
}

func doSomething() error {
    return ErrNotFound
}

Embora essa abordagem seja direta, combinar valores sentinela com tipos de erro personalizados pode ser ainda mais poderoso, permitindo comparação de erros e dados de erro ricos.

Exemplo 3: Erros de agrupamento para mais contexto

Go 1.13 introduziu a função fmt.Errorf com verbo %w, que permite agrupar erros, adicionando mais contexto enquanto preserva o erro original.

package main

import (
    "errors"
    "fmt"
)

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

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
        if errors.Is(err, ErrNotFound) {
            fmt.Println("The resource was not found.")
        }
    }
}

func doSomething() error {
    err := fetchResource()
    if err != nil {
        return fmt.Errorf("failed to do something: %w", err)
    }
    return nil
}

func fetchResource() error {
    return ErrNotFound
}

Isso permite que você verifique erros específicos e também mantenha uma pilha de erros que fornece mais contexto sobre o que deu errado.

Exemplo 4: Enriquecendo Erros com o Método Unwrap()

Go também fornece uma maneira de extrair o erro empacotado usando o método Unwrap(). Ao implementar esse método em seus tipos de erro personalizados, você pode permitir a desempacotamento adicional de erros.

package main

import (
    "errors"
    "fmt"
)

type MyError struct {
    Code    int
    Message string
    Err     error
}

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

func (e *MyError) Unwrap() error {
    return e.Err
}

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println("Error:", err)
        if errors.Is(err, ErrNotFound) {
            fmt.Println("The resource was not found.")
        }
    }
}

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

func doSomething() error {
    err := fetchResource()
    if err != nil {
        return &MyError{
            Code:    500,
            Message: "Something went wrong",
            Err:     err,
        }
    }
    return nil
}

func fetchResource() error {
    return ErrNotFound
}

Aqui, MyError tem um método Unwrap() que retorna o erro empacotado. Isso permite uma inspeção e tratamento mais profundos do erro subjacente.

Exemplo 5: Verificando erros com função erros.As

Go também fornece uma maneira de extrair o erro com o método errors.As. Ao implementar esse método em seus tipos de erro personalizados, você pode verificar o tipo de erro e também buscar os valores de erro personalizados.

package main

import (
    "errors"
    "fmt"
)

type MyError struct {
    Code    int
    Message string
    Err     error
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Code %d: %s: %v", e.Code, e.Message, e.Err)
}

func main() {
    err := doSomething()
    var mErr *MyError
    // another way to initialize custom error
    // mErr := &MyError{}
    if errors.As(err, &mErr) {
        fmt.Println("Error:", mErr)
    }
}

// doSomething attempts to fetch a resource and returns an error if it fails.
// If the error is ErrNotFound, it is wrapped in a MyError with a code of 500.
func doSomething() error {
    err := fetchResource()
    if err != nil {
        return &MyError{
            Code:    500,
            Message: "Something went wrong",
            Err:     err,
        }
    }
    return nil
}

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

func fetchResource() error {
    return ErrNotFound
}

Melhores práticas para erros personalizados no Go

  1. Use erros personalizados com moderação: Erros personalizados são poderosos, mas podem adicionar complexidade. Use-os quando eles oferecem benefícios significativos, como melhor categorização de erros ou contexto adicional.

  2. Aproveite o empacotamento e o desempacotamento: Encapsular erros com contexto adicional e desempacotá-los posteriormente é uma prática recomendada que aprimora a depuração de erros.

  3. Documente seus tipos de erro: Certifique-se de que quaisquer erros personalizados estejam bem documentados para que sua finalidade e uso sejam claros.

  4. Prefira valores de erro para comparação: Quando você precisar comparar erros, considere usar valores de erro predefinidos (erros sentinela) para consistência e clareza.

Conclusão

Erros personalizados em Go fornecem uma maneira flexível e poderosa de gerenciar erros em seus aplicativos. Ao criar seus próprios tipos de erro, agrupar os erros para obter contexto adicional e desembrulhá-los para uma inspeção mais profunda, você pode criar mecanismos de tratamento de erros robustos e sustentáveis. Isso não apenas ajuda na depuração, mas também melhora a qualidade geral do seu código Go.
Escolha sua estratégia com os erros e use os erros consistentes em todo o projeto.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/ankitmalikg/create-custom-errors-in-golang-3mdl?1 Se houver alguma violação, entre em contato com [email protected] para excluí-la
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3