Tratamento de erros em Go: try/catch e além — guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Tratamento de Erros em Go: Filosofia sem try/catch

No mundo do Go (Golang) não existe o mecanismo try/catch familiar para muitos desenvolvedores. Isso não é um acaso, mas uma decisão arquitetônica consciente. Os criadores da linguagem consideraram que o tratamento explícito de erros torna o código mais confiável e legível. Em vez de esconder exceções na pilha de chamadas, o Go propõe que o programador sempre verifique o resultado de cada operação potencialmente perigosa. Neste artigo, vamos analisar todas as principais abordagens para tratamento de erros em Go: desde o básico error até os poderosos panic e recover, além de mostrar como escrever um código que não falhe no momento mais inoportuno.



1. Mecanismo Básico: Interface error

A base do tratamento de erros em Go é a interface embutida error. Ela tem apenas um método:

type error interface {    Error() string}

Qualquer função que possa falhar deve retornar error como o último valor. É convenção retornar nil se não houver erro, e um valor não nulo se ocorrer uma falha.

Exemplo de tratamento básico:

package main

import ( "errors" "fmt")

func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("divisão por zero não é possível") } return a / b, nil}

func main() { result, err := divide(10, 0) if err != nil { fmt.Println("Erro:", err) return } fmt.Println("Resultado:", result)}

Este é o análogo do try/catch em Go — a verificação explícita if err != nil. Essa abordagem força o desenvolvedor a pensar sobre erros a cada passo.



2. Tipos de Erro Personalizados e Encapsulamento (wrapping)

Frequentemente, não basta apenas retornar uma string com a descrição. É necessário passar contexto: onde o erro ocorreu, quais parâmetros foram passados. Para isso, criam-se tipos de erro próprios.

Criação de um erro personalizado:

type DivisionError struct {    Dividend float64    Divisor  float64    Message  string}

func (e *DivisionError) Error() string { return fmt.Sprintf("erro de divisão: %s (dividendo: %f, divisor: %f)", e.Message, e.Dividend, e.Divisor)}

func safeDivide(a, b float64) (float64, error) { if b == 0 { return 0, &DivisionError{Dividend: a, Divisor: b, Message: "divisor é igual a zero"} } return a / b, nil}

Encapsulamento de erros (wrapping):
A partir do Go 1.13, tornou-se possível encapsular um erro dentro de outro, adicionando contexto:

import "fmt"

func readConfig(path string) error { file, err := openFile(path) if err != nil { return fmt.Errorf("não foi possível ler a config %s: %w", path, err) } defer file.Close() // ... leitura do arquivo return nil}

A diretiva %w cria uma cadeia de erros. Posteriormente, você pode verificar se o erro é de um tipo específico usando errors.Is() e errors.As().



3. Panic e Recover: Situações de Emergência

Às vezes, ocorre algo que não deveria acontecer em princípio — acesso fora dos limites de um array, desreferenciamento de um ponteiro nulo. Nesses casos, o Go usa panic. Isso não substitui o try/catch, mas é um mecanismo para erros críticos e irrecuperáveis.

Exemplo de panic:

func main() {    arr := []int{1, 2, 3}    fmt.Println(arr[10]) // panic: runtime error: index out of range}

No entanto, se você quiser "capturar" o pânico e restaurar a execução, usa-se recover em conjunto com defer. Este é o análogo mais próximo do catch.

Exemplo de recover:

func safeCall(f func()) {    defer func() {        if r := recover(); r != nil {            fmt.Pr                

Blogs

Book Recommendations