»

»

Boas práticas de Code Review Golang
Índice:

Boas práticas de Code Review Golang

Índice:

Code review é uma daquelas coisas que todo mundo concorda que é importante, mas a execução costuma ser… bagunçada. O processo pode facilmente descambar para picuinhas, discussões intermináveis sobre estilo ou, pior, virar um ritual de aprovação em que problemas reais passam batido. Para uma linguagem como Go, com opiniões fortes sobre simplicidade e concorrência, um bom processo de Code Review Golang não é só algo legal de ter; é um pilar essencial para construir sistemas estáveis e fáceis de manter.

Se você está desenvolvendo APIs REST, serviços gRPC ou qualquer sistema concorrente em Go para produção, seu processo de code review é sua primeira e melhor linha de defesa. Não se trata apenas de encontrar bugs. É sobre construir um entendimento compartilhado da codebase e elevar o nível de todo o time. Vamos analisar como é uma revisão que realmente funciona.

Por que se importar? O verdadeiro ROI do Code Review

Antes de irmos aos detalhes, vamos deixar o “porquê” bem claro. Pausar para revisar código parece contraintuitivo com prazos apertados, mas o investimento compensa (e muito).

Encontrar bugs mais cedo: Essa é óbvia. Um segundo par de olhos pode identificar um potencial nil pointer dereference, um erro off-by-one ou uma race condition que o autor deixou passar. Encontrar o problema em um PR é infinitamente mais barato do que em produção.

Compartilhamento de conhecimento: Um PR conta a história de uma mudança. Quem revisa aprende sobre uma parte do sistema que talvez não conheça, e o autor pode aprender um novo padrão ou função de uma biblioteca com o feedback. É assim que se quebram os silos de conhecimento.

Garantir a consistência: O tratamento de erros é consistente? O logging é estruturado da mesma forma em todo o serviço? O code review é o momento de garantir esses padrões, fazendo com que a codebase pareça ter sido escrita por um time coeso, e não por uma dúzia de pessoas diferentes.

Melhorar a manutenibilidade: A perspectiva de quem revisa é valiosíssima. Essa pessoa pode fazer a pergunta simples: “Vou entender isso daqui a seis meses?”. Isso força os autores a escreverem um código mais claro e auto-documentado.

O centro da revisão: O que de fato procurar

Ok, você está olhando para um pull request. Onde focar sua energia? É fácil se perder nos detalhes. É útil organizar o raciocínio em torno de algumas áreas-chave.

É Go idiomático?

Go tem um estilo próprio. Código que vai contra o fluxo natural da linguagem é mais difícil de ler e manter para quem já a conhece. Não é apenas uma questão de estética, mas de aproveitar os pontos fortes do Go.

Formatação e Linting: Isso nem deveria ser uma questão. O go fmt é inegociável. Use uma ferramenta como o golangci-lint em seu pipeline de CI para automatizar a checagem de problemas comuns. Isso libera os revisores para focar na lógica, e não no posicionamento de chaves.

Tratamento de erros: Este é um ponto crucial. Os erros estão sendo checados ou simplesmente ignorados com _? Quando um erro é retornado na stack, ele está sendo encapsulado com fmt.Errorf e o verbo %w para preservar o contexto? Estamos usando errors.Is e errors.As corretamente, em vez de comparar strings de mensagens de erro?

Interfaces: As interfaces do Go são poderosas. Observe o princípio “aceite interfaces, retorne structs”. Isso torna o código muito mais fácil de testar e mockar. As interfaces são pequenas e focadas em comportamento (como a io.Reader) ou são monolitos gigantes?

Concorrência: É aqui que se escondem os bugs sutis e traiçoeiros. As goroutines estão sendo lançadas sem um plano claro de quando serão encerradas? Existe potencial para um goroutine leak? Um sync.Mutex está sendo usado corretamente para proteger estado compartilhado, ou um channel seria uma opção melhor? Sempre rode os testes com a flag -race.

Biblioteca Padrão: O autor está reinventando algo que já existe e é super otimizado na biblioteca padrão? (Pense em parsing, encoding/json ou crypto`). Uma verificação rápida pode economizar muito código e evitar bugs

Performance e Uso de Recursos

Para serviços que lidam com tráfego real, a performance não é algo secundário. Você não precisa otimizar tudo prematuramente, mas deve ficar de olho em antipadrões óbvios.

Alocações: O código está criando muito lixo em um `hot path`? Por exemplo, adicionando elementos a um slice em um loop apertado sem pré-alocar a capacidade com make([]T, 0, capacity).

Goroutine Leaks: Vale a pena repetir: isso é um problema tanto de corretude quanto de performance. Uma goroutine que vaza é um vazamento de memória. Se uma goroutine está esperando em um channel que nunca receberá dados, ela ficará presa ali para sempre.

Propagação de Contexto: Em serviços como APIs ou servidores gRPC, o context.Context está sendo passado corretamente pela call stack? Isso é crucial para lidar com deadlines, timeouts e cancelamentos de forma elegante, evitando que seu serviço faça trabalho desnecessário.

O lado humano: Como dar (e receber) um bom feedback

A parte mais difícil do code review não tem nada a ver com código. Tem a ver com pessoas. Uma cultura de revisão ruim pode criar ressentimento e atrasar todo mundo. Uma boa cultura promove colaboração e crescimento.

O objetivo é uma conversa, não um julgamento.

Para quem revisa:

Comece com o “porquê”. Antes de sugerir uma mudança, entenda a intenção do autor. Faça perguntas: “Qual foi a ideia por trás dessa abordagem?” ou “Você considerou o que acontece se esta função retornar um erro?”.

Dê feedback prático. “Isso está confuso” não ajuda. “O nome desta função está um pouco ambíguo; poderíamos renomeá-la para FetchUserByID para ser mais específico?” é muito melhor.

Envie seus comentários em lote. Não dê feedback a conta-gotas ao longo de horas. Faça uma revisão completa e envie seus comentários de uma vez para que o autor possa resolver tudo junto.

Automatize as picuinhas. Se você se pega comentando repetidamente sobre estilo, formatação ou erros simples, é um sinal de que você precisa de uma configuração de linter melhor. Seu tempo é mais valioso que o de uma máquina.

Elogie em público. Se você vir uma solução inteligente ou uma implementação muito limpa, diga! Feedback positivo é tão importante quanto a crítica construtiva.

Para o autor:

Mantenha os PRs pequenos. Esta é a regra de ouro. Um PR de 100 linhas é um prazer de revisar. Um de 2000 linhas é um pesadelo que quase certamente será aprovado sem uma revisão de verdade. Foque em mudanças pequenas, lógicas e atômicas.

Escreva uma boa descrição. Dê contexto. Qual problema isso resolve? Por que essa abordagem foi escolhida? Link para o ticket ou a issue. Uma boa descrição é um ato de empatia com quem vai revisar seu código.

Não leve para o lado pessoal. Feedback sobre seu código não é um feedback sobre você como pessoa. Presuma a boa intenção de quem revisa e foque na substância dos comentários.

Guie quem revisa. Se houver uma área específica sobre a qual você não tem certeza ou quer uma segunda opinião, aponte isso na descrição do PR.


✅ Checklist de Code Review em Golang

Aqui está um checklist prático e direto ao ponto para usar na sua próxima revisão. Você não precisa marcar todas as caixas sempre, mas é um ótimo ponto de partida para criar bons hábitos.

📦 Estrutura e Legibilidade

  • O código é fácil de entender? Um novo membro do time conseguiria ler e entender rapidamente?
  • Nomes de funções, variáveis e pacotes são claros e descritivos?
  • Funções são pequenas e focadas em uma única responsabilidade?
  • O código segue o princípio “aceite interfaces, retorne structs”?
  • A estrutura de pacotes é lógica e não cria dependências circulares?
  • A API pública (exportada) é clara? Nada está exportado sem necessidade?

⚡ Concorrência e Goroutines

  • Cada goroutine iniciada tem um plano claro de término?
  • Existe risco de goroutine leak (bloqueio eterno em channel ou select)?
  • Memória compartilhada entre goroutines está protegida (sync.Mutex ou sync.RWMutex)?
  • channels são usados para comunicação, não como estrutura de dados genérica?
  • context é passado corretamente para lidar com cancelamentos e timeouts?
  • Os testes foram executados com -race para detectar race conditions?

⚠️ Tratamento de Erros

  • Todo erro é checado ou explicitamente ignorado com justificativa (// nolint ou comentário)?
  • Ao propagar erros, usamos fmt.Errorf(... %w ...) para preservar contexto?
  • Erros sentinela (ex.: sql.ErrNoRows) são tratados com errors.Is ou errors.As?
  • Mensagens de erro são úteis para debug, mas não vazam dados sensíveis?

🧪 Testes

  • Há testes suficientes para cobrir a nova lógica?
  • Casos de borda estão cobertos (valores nulos, vazios, erros esperados)?
  • Testes são legíveis e de fácil manutenção (preferir table-driven tests)?
  • Código crítico de performance tem benchmarks?

🚀 Performance

  • Não há alocações desnecessárias em loops críticos (ex.: append sem make pré-alocado)?
  • defer não está sendo usado dentro de loops, para evitar acúmulo desnecessário?
  • Não existem padrões evidentes de N+1 queries ao acessar o banco de dados?

🔒 Segurança

  • Todas as entradas externas são validadas e sanitizadas?
  • Consultas SQL usam queries parametrizadas para evitar SQL injection?
  • Nenhuma informação sensível (senhas, tokens, chaves) aparece em logs?
  • Comparações de valores sensíveis (tokens, assinaturas) usam tempo constante?

Uma cultura forte de code review em Golang é sobre construir um ciclo de feedback. É um processo contínuo de aprendizado e melhoria, tanto para o código quanto para o time. Exige esforço para ir além da simples caça a bugs, mas a recompensa, um sistema mais resiliente, fácil de manter e bem compreendido, vale muito a pena.

Publicado por:
Compartilhe:

Automatize seu Code Review com a Kody

Posts relacionados

Code review é uma daquelas coisas que todo mundo concorda que é importante, mas a execução costuma ser… bagunçada. O processo pode facilmente descambar para picuinhas, discussões intermináveis sobre estilo

Code review é uma daquelas coisas que todo mundo concorda que é importante, mas a execução costuma ser… bagunçada. O processo pode facilmente descambar para picuinhas, discussões intermináveis sobre estilo

Code review é uma daquelas coisas que todo mundo concorda que é importante, mas a execução costuma ser… bagunçada. O processo pode facilmente descambar para picuinhas, discussões intermináveis sobre estilo