Code Review em Go: o que verificar e como dar feedback
Code review não é apenas uma formalidade, mas uma etapa crucial do desenvolvimento. Especialmente em Go, onde a simplicidade e legibilidade do código estão enraizadas na filosofia da linguagem. Para desenvolvedores iniciantes, isso pode parecer assustador: como criticar o código de outra pessoa se você ainda não tem certeza? Na verdade, code review é a melhor maneira de aprender. Neste artigo, vamos analisar o que observar ao revisar código Go e como dar feedback para que seja útil, não ofensivo.
1. Princípios básicos: o que procurar primeiro
Antes de se aprofundar nos detalhes, lembre-se da regra principal: a revisão é sobre o código, não sobre a pessoa. Seu objetivo é encontrar problemas potenciais e melhorar a qualidade do produto, não provar que você é mais inteligente. Comece com coisas simples:
- Erros lógicos: os casos extremos são tratados corretamente? Por exemplo, o que acontece se o slice estiver vazio?
- Pânicos potenciais: você esqueceu o
nil? Verifique se não está chamando métodos em um ponteiro nulo. - Código não utilizado: em Go, isso causa erro de compilação, mas às vezes variáveis ou imports mortos permanecem.
Exemplo de erro típico de iniciante:
func getFirstElement(s []int) int { return s[0] // Pânico se o slice estiver vazio!}O que sugerir na revisão: adicionar uma verificação de comprimento do slice e retornar um erro.
func getFirstElement(s []int) (int, error) { if len(s) == 0 { return 0, fmt.Errorf("slice is empty") } return s[0], nil}2. Expressões idiomáticas do Go: como escrever "à moda Go"
Go não é Java nem Python. Tem seu próprio estilo, que deve ser respeitado. Na revisão, observe os seguintes pontos:
- Nomenclatura: em Go, nomes curtos são comuns (por exemplo,
rpara reader,wpara writer). Não precisa nomear a variável comomyReader— apenasr. - Tratamento de erros: não ignore erros! Se uma função retorna
error, ela deve ser verificada. Exceção:fmt.Printlne similares, mas é melhor registrá-los. - Interfaces: devem ser pequenas. Um método é bom, dois já é demais. Não crie interfaces "para o futuro".
Exemplo de código "não-Go":
func ProcessData(data []string) (bool, error) { var result bool for _, item := range data { if item == "error" { result = false return result, errors.New("found error") } } result = true return result, nil}Aqui, result é desnecessário — você pode retornar true ou false diretamente. Também é melhor usar fmt.Errorf para formatação.
func ProcessData(data []string) (bool, error) { for _, item := range data { if item == "error" { return false, fmt.Errorf("found error in item: %s", item) } } return true, nil}3. Desempenho e memória: o que observar
Embora Go seja rápido, código ruim pode estragar tudo. Na revisão, verifique:
- Evite alocações desnecessárias: se você sabe o tamanho do slice, use
makecom capacidade especificada. - Cópia de structs: structs grandes devem ser passadas por ponteiro para evitar cópias repetidas.
- Goroutines: verifique se você não esqueceu de fechar o canal ou esperar a conclusão da goroutine (use
sync.WaitGroup).
Exemplo de trabalho ruim com slice:
func appendItems(items []int) []int { var result []int for _, v := range items {