Las constantes en Go son valores inmutables cuya representación interna se determina estrictamente durante la compilación, impidiendo cualquier modificación en tiempo de ejecución. A través de la palabra clave const, el lenguaje introduce un sistema de tipado flexible donde una constante puede carecer de un tipo estricto (untyped constants), permitiéndole interactuar con diversos tipos numéricos sin necesidad de conversiones explícitas, siempre que el valor sea representable por el tipo destino.
Este comportamiento de las constantes sin tipo resuelve la rigidez presente en lenguajes como C o Java, donde los literales numéricos suelen estar atados a tamaños de palabra específicos desde su definición. En Go, una constante numérica sin tipo posee una precisión arbitraria de al menos 256 bits, lo que permite realizar cálculos matemáticos complejos con una exactitud superior antes de que el valor sea finalmente asignado a una variable con un tipo de dato concreto, como un float64 o un int32.
Tipado, asignabilidad e inferencia
Cuando se declara una constante con un tipo explícito, como const MaxValue int64 = 1000, el compilador aplica reglas estrictas de assignability. Solo podrá interactuar con variables del mismo underlying type. No obstante, la potencia real de Go reside en las constantes implícitas. Una declaración como const Pi = 3.14159 crea una constante de categoría aritmética (numeric kind). Esta constante puede ser asignada a cualquier variable de punto flotante o incluso compleja, adaptándose al contexto de uso mediante la inferencia de tipos del compilador.
El identificador iota es un mecanismo de generación de secuencias numéricas que opera exclusivamente dentro de los bloques de declaración de constantes. Técnicamente, iota representa una constante entera sucesiva sin tipo que comienza en cero. Su valor se incrementa automáticamente después de cada especificación de constante dentro de un mismo bloque const, facilitando la creación de enumeraciones o conjuntos de flags bit a bit de manera concisa.
package main
import "fmt"
type Role int
const (
// iota inicia en 0
Admin Role = iota // 0
Editor // El tipo y la expresión se repiten implícitamente
Viewer // 2
_ // Saltamos el valor 3 usando el identificador en blanco
Support // 4
)
const (
// iota se reinicia a 0 en cada nuevo bloque const
_ = 1 << (10 * iota) // iota = 0, valor = 1 (1 << 0)
KB // iota = 1, valor = 1024 (1 << 10)
MB // iota = 2, valor = 1048576 (1 << 20)
)
func main() {
fmt.Printf("Role Admin: %d\n", Admin) // → 0
fmt.Printf("Role Support: %d\n", Support) // → 4
fmt.Printf("1 MB en bytes: %d\n", MB) // → 1048576
}
GoLa repetición implícita de la expresión y del tipo en un bloque de constantes permite que, tras definir la primera línea con iota, las líneas subsiguientes hereden el comportamiento sin necesidad de escritura redundante. Si la primera constante utiliza una expresión compleja como 1 << (10 * iota), todas las constantes siguientes aplicarán esa misma fórmula utilizando el valor incremental de iota.
Persistencia del estado de iota en declaraciones múltiples
Un comportamiento que requiere atención es cómo el compilador gestiona el contador de iota cuando una sola línea contiene múltiples identificadores.
Comportamiento de iota en una misma línea de declaración
Dentro de un bloque const, el valor de iota aumenta únicamente por cada línea de declaración (ConstSpec), no por cada identificador. Si se definen varios nombres en una misma línea, todos compartirán el mismo valor de iota. Esto es útil para crear grupos de constantes relacionadas que deben poseer el mismo índice secuencial, pero puede inducir a errores si se asume que cada nombre consume un número de la secuencia. La única forma de avanzar el contador es pasar a la siguiente línea del bloque, lo que garantiza que la estructura de la enumeración sea predecible y visualmente coherente con la disposición del código fuente.
- Módulo: Léxico y Sintaxis Fundamental
- Artículo número: #15