Arrays constantes en Go: cómo declararlos y no volverse loco

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: la pregunta eterna de Stack Overflow

\n\n

Si alguna vez has buscado en Google "Declare a constant array in Go", seguramente has visto ese mismo hilo en Stack Overflow con miles de visitas. Y sí, no estás solo en tu confusión. En Go realmente no se puede simplemente escribir const arr = [...]int{1, 2, 3} — el compilador te dirá un cortés "no".

\n\n

¿Por qué es así? ¿Y qué hacer entonces si necesitamos una lista de datos inmutable? En este artículo analizaremos la naturaleza de las constantes en Go, descubriremos por qué los arrays no pueden ser constantes y encontraremos las mejores soluciones alternativas. Spoiler: la solución existe, y es incluso más elegante de lo que piensas.

\n\n

¿Por qué Go no permite declarar un array constante?

\n\n

Para entenderlo, hay que mirar bajo el capó del lenguaje. En Go, las constantes son valores inmutables calculados en tiempo de compilación. Deben estar estrictamente tipificadas y ser conocidas antes de ejecutar el programa. Los arrays, en cambio, son tipos de datos compuestos que ocupan memoria y pueden modificarse.

\n\n

Aquí hay un ejemplo simple que NO se compilará:

\n\n
package main\n\nconst arr = [3]int{1, 2, 3} // Error: const initializer [3]int{1, 2, 3} is not a constant\n\nfunc main() {\n    fmt.Println(arr)\n}
\n\n

El compilador dice: "¡Oye, esto no es una constante!". Y tiene razón. Incluso si el array se declara como const, Go no garantiza que su contenido no cambiará a través de punteros o slices. Por eso, los desarrolladores del lenguaje decidieron: nada de arrays constantes.

\n\n

Pero no te apresures a frustrarte. Hay al menos tres formas de sortear esta limitación, y cada una tiene sus ventajas.

\n\n

Forma 1: Usar una variable con un comentario "no tocar"

\n\n

La forma más simple e ingenua es simplemente declarar una variable y esperar que nadie la modifique. Pero somos desarrolladores serios, ¿verdad?

\n\n
package main\n\nimport "fmt"\n\n// arr - array constante. Por favor, no lo modifiques.\nvar arr = [3]int{1, 2, 3}\n\nfunc main() {\n    fmt.Println(arr)\n    // arr[0] = 100 // Descomenta esto y todo se romperá\n}
\n\n

Las desventajas son obvias: no es una constante real. Cualquiera puede modificar el array mediante asignación. Pero para prototipos rápidos o proyectos pequeños, sirve.

\n\n

Forma 2: Función getter (el camino correcto)

\n\n

Este enfoque se usa en código de producción. Ocultamos el array dentro de una función y devolvemos una copia del mismo. Así, nadie podrá modificar el original.

\n\n
package main\n\nimport "fmt"\n\n// getColors devuelve una copia del array de colores.\n// El array está protegido contra modificaciones externas.\nfunc getColors() [3]string {\n    return [3]string{"Rojo", "Verde", "Azul"}\n}\n\nfunc main() {\n    colors := getColors()\n    fmt.Println(colors)\n    // colors[0] = "Amarillo" // Esto modifica la copia, no el original\n}
\n\n

¿Por qué esto es bueno? Porque:

\n
    \n
  • El array no puede modificarse desde fuera: la función devuelve una copia.
  • \n
  • El código es legible y comprensible.
  • \n
  • Es fácil de probar y mantener.
  • \n
\n\n

Pero hay un detalle: cada llamada a la función crea una nueva copia del array. Si el array es grande (por ejemplo, 1000 elementos), esto puede ser costoso. En ese caso, usa la siguiente forma.

\n\n

Forma 3: Variable de paquete con acceso privado

\n\n

Si estás escribiendo un paquete y quieres proteger el array de modificaciones, hazlo no exportable (con minúscula) y proporciona acceso a través de una función.

\n\n
package constants\n\n// El array solo es accesible dentro del paquete\nvar defaultPorts = [5]int{80, 443, 8080, 3000, 5000}\n\n// GetDefaultPorts devuelve una copia del array de puertos.\nfunc GetDefaultPorts() [5]int {\n    return defaultPorts\n}
\n\n

Ahora los usuarios de tu paquete solo pueden leer los datos, pero no modificarlos. Ideal para bibliotecas.

\n\n

Forma 4: Uso de iota para conjuntos constantes

\n\n

¿Y si lo que necesitas no son los valores en sí, sino sus índices? Por ejem

Blogs

Book Recommendations