Como Tratar Erros em Go: Um Guia Prático
Aprenda a tratar erros em Go com exemplos executáveis: retorne um erro, confira o resultado, acrescente contexto com %w e reconheça um arquivo ausente com errors.Is.

Nesta página
Como Tratar Erros em Go: Um Guia Prático
Programas encontram problemas: um arquivo não existe, um número é inválido ou uma requisição de rede falha. Em Go, uma função normalmente retorna um valor de erro para que a função que a chamou decida o que fazer. Você verá esse padrão em uma conta pequena e depois em um programa que lê um arquivo de verdade.
Este guia continua Seu Primeiro Programa em Go. Se você já usou defer para fazer a limpeza, guarde a ideia: tratar o erro define o que fazer quando uma operação falha; defer ajuda a liberar recursos depois de uma preparação bem-sucedida.

Retorne um valor e um erro
Uma função Go pode retornar mais de um valor. Uma assinatura comum é (resultado, error): devolva o resultado com nil em caso de sucesso, ou um valor zero com um erro diferente de nil em caso de falha.
Salve o exemplo como main.go e rode go run main.go:
1package main
2
3import (
4 "errors"
5 "fmt"
6)
7
8func dividir(a, b int) (int, error) {
9 if b == 0 {
10 return 0, errors.New("não é possível dividir por zero")
11 }
12 return a / b, nil
13}
14
15func main() {
16 for _, divisor := range []int{2, 0} {
17 resultado, err := dividir(12, divisor)
18 if err != nil {
19 fmt.Println("a divisão falhou:", err)
20 continue
21 }
22 fmt.Println("resultado:", resultado)
23 }
24}resultado: 6
a divisão falhou: não é possível dividir por zeroO teste if err != nil aparece antes de usar resultado. Quem chamou a função pode tentar outra entrada, mostrar uma mensagem ou devolver o erro para seu próprio chamador. Um erro é um valor; não é uma ordem para encerrar o programa.
Leia um arquivo e acrescente contexto
Agora substitua o conteúdo de main.go pelo programa abaixo. Ele lê um arquivo de texto local chamado mensagem.txt. Há dois resultados úteis: mostrar o conteúdo ou avisar que o arquivo não existe.
1package main
2
3import (
4 "errors"
5 "fmt"
6 "os"
7 "strings"
8)
9
10func carregarMensagem(caminho string) (string, error) {
11 dados, err := os.ReadFile(caminho)
12 if err != nil {
13 return "", fmt.Errorf("carregar mensagem %q: %w", caminho, err)
14 }
15 return strings.TrimSpace(string(dados)), nil
16}
17
18func main() {
19 mensagem, err := carregarMensagem("mensagem.txt")
20 if err != nil {
21 if errors.Is(err, os.ErrNotExist) {
22 fmt.Println("mensagem.txt não existe; crie o arquivo e tente novamente")
23 return
24 }
25 fmt.Println("não foi possível carregar a mensagem:", err)
26 return
27 }
28 fmt.Println("mensagem:", mensagem)
29}Rode em uma pasta sem mensagem.txt:
mensagem.txt não existe; crie o arquivo e tente novamenteDepois crie mensagem.txt com o texto Olá, Go! e rode outra vez:
mensagem: Olá, Go!O programa usa os.ReadFile, que lê e fecha o arquivo para você. Se você abrir um arquivo com os.Open, precisará fechá-lo; aí defer arquivo.Close() costuma ser útil.
Por que %w e errors.Is funcionam juntos?
Esta linha acrescenta a operação e o nome do arquivo ao erro:
return "", fmt.Errorf("carregar mensagem %q: %w", caminho, err)O verbo %w encapsula o erro original. As palavras extras ajudam a entender onde a falha aconteceu, mas o erro original continua disponível para inspeção. errors.Is(err, os.ErrNotExist) percorre essa cadeia e reconhece o arquivo ausente mesmo depois que carregarMensagem acrescenta contexto. A mensagem exata produzida por os.ReadFile pode variar entre sistemas operacionais; verificar a identidade do erro é mais confiável do que procurar palavras no texto.
Com %v no lugar de %w, a mensagem ainda aparece, mas o erro original não fica encapsulado para errors.Is encontrá-lo. Comparar diretamente o erro encapsulado com err == os.ErrNotExist também pode deixar passar a correspondência. Encapsule um erro quando quem chama a função precisa reconhecê-lo ou inspecioná-lo; em uma função pública, essa escolha pode fazer parte da API.
Uma tabela para decidir
| Situação | Resposta comum |
|---|---|
| A função conclui o trabalho | Retorne o resultado e nil |
| A função não consegue concluir | Retorne um valor zero e um erro com contexto útil |
| Quem chamou consegue se recuperar | Confira o erro e siga um caminho alternativo |
| Quem chamou não consegue se recuperar | Devolva o erro ou mostre-o no limite do programa |
Não ignore um erro só para encurtar o código. panic não é a resposta normal para uma situação esperada, como a ausência de um arquivo fornecido pelo usuário.
Experimente
Modifique carregarMensagem para devolver um erro quando o arquivo estiver vazio ou contiver apenas espaços. Preserve o tratamento do arquivo ausente. Uma resposta possível é:
1func carregarMensagem(caminho string) (string, error) {
2 dados, err := os.ReadFile(caminho)
3 if err != nil {
4 return "", fmt.Errorf("carregar mensagem %q: %w", caminho, err)
5 }
6 mensagem := strings.TrimSpace(string(dados))
7 if mensagem == "" {
8 return "", fmt.Errorf("carregar mensagem %q: o arquivo está vazio", caminho)
9 }
10 return mensagem, nil
11}Faça três testes: sem arquivo, com arquivo vazio e com texto. O caso do arquivo ausente ainda deve corresponder a os.ErrNotExist; o arquivo vazio deve chegar à mensagem geral de erro.
Cola rápida
1valor, err := fazerTrabalho()
2if err != nil {
3 if errors.Is(err, os.ErrNotExist) {
4 // Trate especificamente um arquivo ausente.
5 }
6 return fmt.Errorf("fazer trabalho: %w", err)
7}
8usar(valor)Confira os erros quando surgem, acrescente contexto enquanto eles sobem pelas funções e escolha a mensagem para a pessoa no limite do programa. Esse ritmo simples resolve muitas falhas do dia a dia sem esconder o que aconteceu.
Para saber mais
Leia a seguir

O Que É a Linguagem de Programação Rust? Um Guia Simples da Linguagem Rápida Que Não Deixa Você Travar
Um guia simples e sem jargões sobre o Rust, a linguagem tão rápida quanto o C que impede famílias inteiras de erros de memória antes de o programa rodar. Entenda a ideia de posse, por que gigantes da tecnologia o adotam e onde ele é usado.

O Que É a Linguagem de Programação Go? Um Guia Simples da Linguagem da Nuvem
Um guia simples e sem jargões sobre o Go, a linguagem simples e rápida que o Google criou para a nuvem. Entenda o que são goroutines, por que um programa Go é um arquivo só e como o Go passou a mover o Docker, o Kubernetes e boa parte da internet.

O Que É a Linguagem de Programação Ruby? Um Guia Simples da Linguagem Feita para a Felicidade
Um guia simples e sem jargões sobre o Ruby, a linguagem de programação feita para deixar os programadores felizes. Entenda por que o código Ruby parece inglês, como o Ruby on Rails move sites como GitHub e Shopify, e onde o Ruby brilha.
Comentários
Seja gentil e específico. Comentários com links de contas novas aparecem depois da análise de um moderador.