Erros comuns em Go: o que você deve evitar
Eu, como programador sênior e autor do Yurideveloper, compartilho neste post
um guia direto ao ponto sobre armadilhas frequentes em Go e como evitá-las com
padrões simples e eficaz.
1) Nil, zero value e inicialização indevida
Go trata mapas, slices e ponteiros de forma diferente entre zero value e valor inicial. Muitos erros surgem quando esperamos que um mapa ou slice já esteja pronto para uso.
- Declarar var m map[string]int sem fazer make: o mapa permanece nil e leituras/escritas falham com runtime panic.
- Conferir apenas a presença de chave sem considerar o estado do mapa/slice pode levar a resultados inesperados.
- Não inicializar colunas de dados antes de enviar para canais, bancos ou APIs locais pode trazer concorrência imprevisível.
Práticas recomendadas: sempre inicialize estruturas com make/new ou use literals quando possível. Emite checagens antes de operações com mapas e slices para evitar panics.
2) Ponteiros, interfaces e nil
Erros comuns aparecem quando confundimos nil de uma interface com nil de um ponteiro ou quando manipulamos ponteiros sem checagem adequada.
- Interface nil não é o mesmo que valor concreto; verificar apenas se
err != nilnão cobre casos com interfaces vazias. - Dereferenciar ponteiros sem inicialização pode levar a panic. Use checagens claras ou construtores/validações antes de usar o ponteiro.
- Quando retornar interfaces, confirme se o tipo implementa o método esperado ou use type assertions com checagem segura.
Dicas rápidas: prefira valores concretos quando possível e mantenha a hierarquia de erros clara para facilitar o debug.
3) Concorrência mal gerida
Go facilita a concorrência, mas demandas de sincronização, cancelamento e compartilhamento de dados exigem disciplina para evitar race conditions e deadlocks.
- Goroutines sem sincronização podem atualizar estados compartilhados de forma não determinística.
- Não fechar canais corretamente pode deixar receivers esperando indefinidamente ou provocar failed sends.
- Contextos e deadlines ajudam a manter a aplicação responsiva sob carga ou operações bloqueantes.
Boas práticas: utilize mutexes quando necessário, prefira canais para comunicação entre goroutines e propagate cancelamentos com context.Context.
4) Tratamento de erros: não subestime o contexto
O tratamento de erros em Go frequentemente é subutilizado ou mal executado. Embutir contexto ao erro facilita o diagnóstico sem perder a run atual.
- Ignorar erros, especialmente em chamadas de IO, bancos ou rede, leva a falhas silenciosas.
- Não embrulhar erros com contexto dificulta entender a causa raiz quando o fluxo retorna a níveis mais altos.
- Comparações diretas com erros específicos sem usar errors.Is/ errors.As reduz a flexibilidade frente a wrapping de erros.
// Exemplo: embrulhar com contexto e usar wrap
package main
import (
"errors"
"fmt"
)
func loadConfig() (string, error) {
return "", errors.New("arquivo não encontrado")
}
func main() {
if cfg, err := loadConfig(); err != nil {
// embrulha com contexto
err = fmt.Errorf("loadConfig falhou: %w", err)
fmt.Println(err) // output: loadConfig falhou: arquivo não encontrado
return
} else {
fmt.Println("config loaded:", cfg)
}
}
Sugestão: adote um padrão de retorno de erro claro com contexto, e utilize errors.Is / errors.As quando precisar de checagens específicas.
Sou Apaixonado pela programação e estou trilhando o caminho de ter cada diz mais conhecimento e trazer toda minha experiência vinda do Design para a programação resultando em layouts incríveis e idéias inovadoras! Conecte-se Comigo!