Code Review en Go: qué revisar y cómo dar retroalimentación en la práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué el code review en Go no es solo una marca

\n

El code review no es un procedimiento burocrático, sino un elemento clave de la cultura de desarrollo. En Go, con su sintaxis concisa y reglas estrictas, la revisión a menudo se convierte en el primer filtro que elimina problemas en una etapa temprana. Muchos equipos que migran a Golang se enfrentan a que los viejos hábitos (por ejemplo, de Python o PHP) no funcionan: Go perdona menos errores relacionados con tipos, pero requiere atención a los detalles.

\n

En la práctica, el code review en Go resuelve tres tareas: capacitación del equipo (los novatos se integran más rápido al estilo de código), mejora de la calidad (detección de errores y antipatrones) y consistencia del código (para que el proyecto no se convierta en una "colcha de retazos"). Analicemos exactamente qué observar y cómo formular observaciones.

\n\n

1. ¿Qué revisar primero?: desde sintaxis hasta errores

\n

Cualquier revisión comienza con lo básico. En Go hay varios "puntos críticos" que vale la pena verificar automática o manualmente.

\n\n

1.1. Manejo de errores (error handling)

\n

Go no usa excepciones: los errores se devuelven como valores. Un problema común: el desarrollador ignora el error devuelto usando _. Esto solo es aceptable en casos raros (por ejemplo, fmt.Println).

\n
// Mal: se ignora el error\nresp, _ := http.Get("https://api.example.com/data")\n\n// Bien: se maneja el error\nresp, err := http.Get("https://api.example.com/data")\nif err != nil {\n    log.Printf("no se pudieron obtener los datos: %v", err)\n    return err\n}\ndefer resp.Body.Close()
\n

Qué revisar:

\n
    \n
  • ¿Se manejan todos los errores (no solo con _)?
  • \n
  • ¿Se usa defer para cerrar recursos (archivos, conexiones)?
  • \n
  • ¿No se "tragan" los errores en las gorutinas?
  • \n
\n\n

1.2. Nomenclatura y estilo (Go idioms)

\n

Go exige brevedad: camelCase para privados, PascalCase para exportados. Evite la "notación húngara" y nombres largos.

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

Señales de alerta:

\n
    \n
  • Nombres de variables como temp, data, val (demasiado genéricos).
  • \n
  • Funciones de más de 30-40 líneas (hay que dividirlas).
  • \n
  • Falta de comentarios en funciones exportadas (es un requisito de golint).
  • \n
\n\n

1.3. Gorutinas y sincronización

\n

Esta es la parte más compleja. Los errores en código concurrente son una fuente frecuente de bugs en producción.

\n
// Mal: condición de carrera (data race)\nvar counter int\nfor i := 0; i < 100; i++ {\n    go func() {\n        counter++ // inseguro\n    }()\n}\n\n// Bien: usamos un 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

Qué revisar:

\n
    \n
  • ¿Hay sync.Mutex o atomic para datos compartidos?
  • \n
  • ¿Se olvidaron de cerrar el canal (close(ch))?
  • \n
  • ¿No "fugan" gorutinas (sin select con timeout)?
  • \n
\n\n

2. Revisiones arquitectónicas: desde interfaces hasta paquetes

\n

Después de la sintaxis básica, observamos la estructura del código. Go fomenta la composición, no la herencia.

\n\n

2.1. Interfaces: pequeñas y del lado del consumidor

\n

En Go, las interfaces se implementan implícitamente. Una buena interfaz contiene 1-3 métodos. Verifique si el autor no intenta hacer una interfaz "todopoderosa".

\n
// Mal: interfaz 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