Introdução ao tratamento de erros em Go
Go (Golang) é uma linguagem compilada moderna, desenvolvida no Google. Uma de suas principais características é a abordagem para tratamento de erros, que difere radicalmente do mecanismo familiar try/catch do Java, Python ou JavaScript. Go não possui exceções no sentido clássico. Em vez disso, a linguagem usa uma transmissão explícita e "manual" de erros por meio de valores de retorno. Essa abordagem pode parecer incômoda para iniciantes, mas torna o código mais previsível, legível e resistente a bugs ocultos.
Neste artigo, vamos detalhar a filosofia de tratamento de erros em Go: desde a interface básica error até os mecanismos panic e recover. Você aprenderá por que o Go abandonou o try/catch e como escrever código confiável sem falhas repentinas.
Por que o Go não tem try/catch?
Os desenvolvedores do Go (Rob Pike, Ken Thompson e Robert Griesemer) conscientemente abandonaram as exceções. Os principais motivos são:
- Explicitude: Um erro é simplesmente um valor que a função retorna explicitamente. O programador sempre vê que a função pode terminar com um erro.
- Fluxo de execução não poluído: Em linguagens com exceções, o código frequentemente "pula" para um bloco catch, quebrando a linearidade. Em Go, o fluxo de execução permanece previsível.
- Ausência de erros ocultos: Exceções podem não ser capturadas, levando a falhas. Em Go, você é obrigado a tratar o erro (ou ignorá-lo explicitamente com
_).
Em vez de try/catch, Go oferece um idioma simples, mas poderoso:
result, err := doSomething()if err != nil { // Tratamento do erro log.Fatal(err)}// Trabalhar com resultEsse padrão é encontrado em todo o Go. Ele não requer construções especiais e torna o tratamento de erros parte do fluxo normal do código.
Interface error e criação de erros personalizados
Interface error embutida
Em Go, os erros implementam a interface embutida:
type error interface { Error() string}Qualquer tipo que tenha um método Error() string automaticamente satisfaz essa interface. A função padrão errors.New() cria um erro simples:
import "errors"
err := errors.New("algo deu errado")fmt.Println(err.Error()) // "algo deu errado"Criação de tipos de erro personalizados
Para informações detalhadas, criam-se estruturas personalizadas:
type MyError struct { Code int Message string}
func (e *MyError) Error() string { return fmt.Sprintf("erro %d: %s", e.Code, e.Message)}
func riskyOperation() error { return &MyError{Code: 404, Message: "não encontrado"}}
func main() { err := riskyOperation() if err != nil { // type assertion para obter detalhes if myErr, ok := err.(*MyError); ok { fmt.Printf("Código: %d, Mensagem: %s", myErr.Code, myErr.Message) } }}Isso permite transmitir junto com o erro quaisquer dados adicionais: status HTTP, códigos de erro, timestamps, etc.
Trabalhando com pânico (panic) e recuperação (recover)
Embora Go evite exceções, ele possui um mecanismo panic para situações críticas (por exemplo, estouro de array ou divisão por zero). panic não substitui try/catch, é um interruptor de emergência.
Quando usar panic?
- Em estados inesperados que não podem ser tratados (por exemplo, erro na inicialização do programa).
- Em testes e protótipos (mas não em código de produção sem extrema necessidade).
Mecanismo recover
recover() permite "capturar" um pânico e continuar a execução. Ele funciona apenas dentro de uma função adiada (defer):
Blogs
Book Recommendations
Leia também
Swift para aprendizado de máquina: possibilidades e limitações
Como concatenar vetores em Rust: 5 principais erros e suas soluções
Como mudar o Java JDK no macOS: 5 erros de iniciantes e suas soluções
Implantação de PHP no Kubernetes: guia prático passo a passo
Trabalhando com WebAssembly e JavaScript: do A ao Z no Node.js