Code Review en Go: qué revisar y cómo dar retroalimentación
El code review no es solo una formalidad, sino una etapa crucial del desarrollo. Especialmente en Go, donde la simplicidad y legibilidad del código están arraigadas en la filosofía del lenguaje. Para los desarrolladores principiantes, esto puede parecer intimidante: ¿cómo criticar el código de otros si uno mismo aún no está seguro? En realidad, el code review es la mejor manera de aprender. En este artículo, analizaremos a qué prestar atención al revisar código Go y cómo dar retroalimentación para que sea útil, no ofensiva.
1. Principios básicos: qué buscar primero
Antes de profundizar en los detalles, recuerde la regla principal: la revisión es sobre el código, no sobre la persona. Su objetivo es encontrar problemas potenciales y mejorar la calidad del producto, no demostrar que es más inteligente. Comience con cosas simples:
- Errores lógicos: ¿se manejan correctamente los casos límite? Por ejemplo, ¿qué sucede si el slice está vacío?
- Pánicos potenciales: ¿olvidó el
nil? Verifique que no esté llamando métodos en un puntero nulo. - Código no utilizado: en Go esto provoca un error de compilación, pero a veces quedan variables o importaciones muertas.
Ejemplo de un error típico de principiante:
func getFirstElement(s []int) int { return s[0] // ¡Pánico si el slice está vacío!}Qué sugerir en la revisión: agregar una verificación de la longitud del slice y devolver un error.
func getFirstElement(s []int) (int, error) { if len(s) == 0 { return 0, fmt.Errorf("slice is empty") } return s[0], nil}2. Modismos de Go: cómo escribir "a la go"
Go no es Java ni Python. Tiene su propio estilo que debe respetarse. En la revisión, preste atención a los siguientes puntos:
- Nombres: en Go se usan nombres cortos (por ejemplo,
rpara reader,wpara writer). No es necesario llamar a una variablemyReader— simplementer. - Manejo de errores: ¡no ignore los errores! Si una función devuelve
error, debe verificarse. La excepción esfmt.Printlny similares, pero incluso es mejor registrarlos. - Interfaces: deben ser pequeñas. Un método está bien, dos ya es demasiado. No cree interfaces "por si acaso".
Ejemplo de código "no-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}Aquí result no es necesario — se puede devolver directamente true o false. También se debe usar fmt.Errorf para formatear.
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. Rendimiento y memoria: a qué prestar atención
Aunque Go es bastante rápido, un código deficiente puede arruinarlo todo. En la revisión, verifique:
- Evite asignaciones innecesarias: si conoce el tamaño del slice, use
makeespecificando la capacidad. - Copia de estructuras: las estructuras grandes es mejor pasarlas por puntero para no copiarlas cada vez.
- Gorutinas: verifique si olvidó cerrar el canal o esperar a que la gorutina termine (use
sync.WaitGroup).
Ejemplo de mal trabajo con slice:
func appendItems(items []int) []int { var result []int for _, v := range items {