Code review em Go: o que verificar e como dar feedback
Code review (revisão de código) não é apenas uma formalidade, mas uma das ferramentas mais eficazes para melhorar a qualidade do código, compartilhar conhecimento na equipe e prevenir bugs. Na comunidade Go (Golang), o code review tem um significado especial, pois a linguagem incentiva simplicidade, legibilidade e idiomática. Neste artigo, vamos analisar o que observar ao revisar código Go e como dar feedback para que ele seja útil, e não ofensivo.
1. Princípios gerais do code review em Go
Antes de passar para os detalhes técnicos, é importante lembrar da cultura de revisão. Seu objetivo é melhorar o código e ajudar o colega, não provar que você está certo. Aqui estão algumas regras de ouro:
- Seja construtivo. Em vez de "isso é ruim", escreva "aqui pode haver um vazamento de goroutine, vamos adicionar um contexto".
- Pergunte, não afirme. "Por que você escolheu
sync.Mutexem vez de um canal?" é uma boa pergunta. "Você é burro, deveria ter usado um canal" é ruim. - Não atrase a revisão. Tente responder dentro de 24 horas (ou conforme combinado na equipe).
- Foque na lógica e na arquitetura. Correções estilísticas (espaços, indentação) é melhor deixar para o
gofmt.
2. O que verificar primeiro: checklist para Go
Aqui está uma lista estruturada do que vale a pena observar ao revisar código Go. Vamos dividi-la em blocos lógicos.
2.1. Tratamento de erros
Em Go não há exceções, erros são valores. Esta é uma das principais expressões idiomáticas da linguagem.
- Verifique todos os erros retornados. Ignorar um erro com
_só é permitido em casos muito raros (por exemplo, ao escrever emio.Discard). - Não use
panicpara erros comuns.panicé para estados irrecuperáveis (por exemplo, erro de inicialização do servidor). - Encapsule erros. Use
fmt.Errorf("algo deu errado: %w", err)para adicionar contexto. Isso permite usarerrors.Is()eerrors.As().
// Ruim: perda de contextoif err != nil { return err}
// Bom: encapsulamos o erroif err != nil { return fmt.Errorf("não foi possível abrir o arquivo %s: %w", filename, err)}2.2. Goroutines e concorrência
Go é famoso por sua concorrência leve, mas ela também é fonte de muitos bugs.
- Vazamentos de goroutines. Certifique-se de que cada goroutine iniciada um dia será finalizada. Use contexto (
context.Context) para cancelamento. - Uso correto de canais. Quem cria o canal, o fecha. Fechar o canal é responsabilidade do remetente.
- Data race (condição de corrida). Evite escrever simultaneamente em uma mesma variável sem sincronização. Use mutexes (
sync.Mutex) ou atômicos (sync/atomic).
// Exemplo com contexto para cancelar goroutinefunc process(ctx context.Context, dataCh chan int) { for { select { case <-ctx.Done(): log.Println("Encerrando trabalho") return case val, ok := <-dataCh: if !ok { return // canal fechado } fmt.Println(val) } }}2.3. Expressões idiomáticas e estilo Go
Go é uma linguagem onde a legibilidade do código é valorizada acima de tudo.
- Nomes de variáveis. Nomes curtos para escopos curtos.
ipara loop,rpara reader. Para variáveis globais, nomes mais longos. - Evite "números mágicos". Use constantes.