Clean Code en Go: principios y ejemplos prácticos

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

Clean Code en Go: principios y ejemplos prácticos

\n\n

Go es un lenguaje que desde el principio fue diseñado con énfasis en la simplicidad y la legibilidad. Sin embargo, incluso en un lenguaje tan conciso se puede escribir código enredado y difícil de mantener. El concepto de Clean Code (código limpio) ayuda a los desarrolladores a crear programas que sean fáciles de leer, probar y modificar. En este artículo analizaremos los principios clave de Clean Code aplicados a Go y veremos ejemplos concretos.

\n\n

¿Por qué es importante el código limpio en Go?

\n\n

Go se utiliza a menudo para crear microservicios, API y sistemas de alta carga. En tales proyectos, un equipo de desarrolladores trabaja con el código. El código limpio reduce la carga cognitiva, acelera las revisiones de código y disminuye la cantidad de errores. El objetivo principal es escribir código que sea comprensible no solo para el autor, sino también para cualquier otro desarrollador que lo vea por primera vez.

\n\n

1. Nomenclatura de variables y funciones

\n\n

Una nomenclatura adecuada es la base del código limpio. En Go se acostumbra usar nombres cortos para variables locales y nombres más largos para entidades globales.

\n\n

Ejemplo malo

\n
package main\n\nfunc f(x int, y string) int {\n    z, _ := strconv.Atoi(y)\n    return x + z\n}\n
\n\n

Ejemplo bueno

\n
package main\n\nfunc addPriceToCount(count int, priceStr string) int {\n    price, _ := strconv.Atoi(priceStr)\n    return count + price\n}\n
\n\n

Reglas de nomenclatura en Go:

\n
    \n
  • Use camelCase para variables no exportadas (privadas).
  • \n
  • Use PascalCase para funciones y tipos exportados (públicos).
  • \n
  • Evite nombres de una sola letra, excepto para índices en bucles (i, j).
  • \n
  • No incluya el tipo de variable en su nombre (por ejemplo, priceInt es malo, price es bueno).
  • \n
\n\n

2. Estructura de paquetes y archivos

\n\n

En Go, cada paquete debe resolver una sola tarea. Divida el código por responsabilidad. La estructura estándar de un proyecto se ve así:

\n\n
myproject/\n├── cmd/\n│   └── server/\n│       └── main.go\n├── internal/\n│   ├── handler/\n│   ├── service/\n│   └── repository/\n├── pkg/\n│   └── utils/\n└── go.mod\n
\n\n

Principio: El paquete internal protege el código de importaciones externas. El paquete pkg contiene utilidades reutilizables. En cmd se almacenan los puntos de entrada (archivos main.go).

\n\n

Ejemplo malo

\n
// El paquete "utils" contiene de todo\npackage utils\n\nfunc Calculate(x, y int) int { ... }\nfunc SendEmail(to string) { ... }\nfunc ParseJSON(data []byte) { ... }\n
\n\n

Ejemplo bueno

\n
// El paquete "calculator" solo se encarga de cálculos\npackage calculator\n\nfunc Add(a, b int) int { return a + b }\n
\n\n

3. Manejo de errores en Go

\n\n

En Go no hay excepciones: los errores se devuelven como valores. El código limpio requiere un manejo explícito y significativo de cada error.

\n\n

Ejemplo malo

\n
func readFile(path string) string {\n    data, _ := os.ReadFile(path) // ignoramos el error\n    return string(data)\n}\n
\n\n

Ejemplo bueno

\n
func readFile(path string) (string, error) {\n    data, err := os.ReadFile(path)\n    if err != nil {\n        return "", fmt.Errorf("read file %s: %w", path, err)\n    }\n    return string(data), nil\n}\n
\n\n

Consejos para el manejo de errores:

\n
    \n
  • Nunca ignore los errores usando _.
  • \n
  • Siempre agregue contexto: fmt.Errorf("operation: %w", err).
  • \n
  • Use tipos de error personalizados para diferentes situaciones.
  • \n
  • No use panic para errores comunes, solo para situaciones verdaderamente excepcionales.
  • \n
\n\n

4. Funciones: longitud y responsabilidad

\n\n

Una función

Blogs

Book Recommendations