Code Review em Go: o que verificar e como dar feedback na prática

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

Introdução: por que code review em Go não é apenas uma formalidade

\n

Code review não é um procedimento burocrático, mas um elemento-chave da cultura de desenvolvimento. Em Go, com sua sintaxe concisa e regras rigorosas, a revisão frequentemente se torna o primeiro filtro que elimina problemas em estágio inicial. Muitas equipes que migram para Golang descobrem que velhos hábitos (por exemplo, do Python ou PHP) não funcionam: Go perdoa menos erros relacionados a tipos, mas exige atenção aos detalhes.

\n

Na prática, o code review em Go resolve três tarefas: treinamento da equipe (iniciantes se adaptam mais rápido ao estilo de código), aumento da qualidade (busca de bugs e antipadrões) e consistência do código (para que o projeto não se torne uma "colcha de retalhos"). Vamos analisar exatamente o que observar e como formular observações.

\n\n

1. O que verificar primeiro: da sintaxe aos erros

\n

Qualquer revisão começa com o básico. Em Go, existem vários "pontos críticos" que devem ser verificados automática ou manualmente.

\n\n

1.1. Tratamento de erros (error handling)

\n

Go não usa exceções — os erros são retornados como valores. Um problema comum: o desenvolvedor ignora o erro retornado usando _. Isso só é aceitável em casos raros (por exemplo, fmt.Println).

\n
// Ruim: erro ignorado\nresp, _ := http.Get("https://api.example.com/data")\n\n// Bom: erro tratado\nresp, err := http.Get("https://api.example.com/data")\nif err != nil {\n    log.Printf("não foi possível obter dados: %v", err)\n    return err\n}\ndefer resp.Body.Close()
\n

O que verificar:

\n
    \n
  • Todos os erros foram tratados (não apenas com _)?
  • \n
  • defer está sendo usado para fechar recursos (arquivos, conexões)?
  • \n
  • Erros em goroutines não estão sendo "engolidos"?
  • \n
\n\n

1.2. Nomenclatura e estilo (Go idioms)

\n

Go exige concisão: camelCase para privados, PascalCase para exportados. Evite "notação húngara" e nomes longos.

\n
// Ruim\nfunc GetUserDataFromDatabase(userID int) (*UserData, error)\n\n// Bom\nfunc GetUser(id int) (*User, error)
\n

Bandeiras vermelhas:

\n
    \n
  • Nomes de variáveis como temp, data, val (muito genéricos).
  • \n
  • Funções com mais de 30-40 linhas (precisam ser divididas).
  • \n
  • Falta de comentários em funções exportadas (exigência do golint).
  • \n
\n\n

1.3. Goroutines e sincronização

\n

Esta é a parte mais complexa. Erros em código concorrente são uma fonte frequente de bugs em produção.

\n
// Ruim: condição de corrida (data race)\nvar counter int\nfor i := 0; i < 100; i++ {\n    go func() {\n        counter++ // inseguro\n    }()\n}\n\n// Bom: usando mutex\nvar mu sync.Mutex\nvar counter int\nfor i := 0; i < 100; i++ {\n    go func() {\n        mu.Lock()\n        counter++\n        mu.Unlock()\n    }()\n}
\n

O que verificar:

\n
    \n
  • Há sync.Mutex ou atomic para dados compartilhados?
  • \n
  • O canal foi fechado (close(ch))?
  • \n
  • Goroutines não estão "vazando" (sem select com timeout)?
  • \n
\n\n

2. Verificações arquiteturais: de interfaces a pacotes

\n

Após a sintaxe básica, observamos a estrutura do código. Go incentiva composição, não herança.

\n\n

2.1. Interfaces: pequenas e do lado do consumidor

\n

Em Go, interfaces são implementadas implicitamente. Uma boa interface contém 1-3 métodos. Verifique se o autor não está tentando criar uma interface "abrangente".

\n
// Ruim: interface enorme\ntype Storage interface {\n    Save(data []byte) error\n    Load(id string) ([]byte, error)\n    Delete(id string) error\n    List() ([]string, error)\n    Connect() error\                

Blogs

Book Recommendations