Menu

const en Golang: constantes con tipo y sin tipo

Cómo funciona const en Go: declarar constantes, la diferencia entre constantes con tipo y sin tipo, expresiones constantes con precisión arbitraria y por qué Go no tiene slices, maps ni structs constantes.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Una constante es un valor fijado en tiempo de compilación. Se declara con const, y Go rechaza cualquier intento de cambiarla.

Las constantes se pueden declarar a nivel de paquete o dentro de una función, una por línea o agrupadas en un bloque const ( ... ). MB y GB se calculan a partir de otras constantes, y el compilador hace esa aritmética una sola vez, al compilar.

Asignar a una constante, como MaxRetries = 5, es un error de compilación:

./main.go:8:2: cannot assign to MaxRetries (neither addressable nor a map index expression)

Qué puede ser una constante

Solo tres clases de valores: booleanos, números (enteros, flotantes, complejos y runes) y strings. El compilador tiene que poder calcular el valor, lo que significa literales, otras constantes, aritmética sobre ellas y unas pocas funciones integradas como len de un string constante.

Todo lo que necesite ejecutar código o reservar memoria queda fuera:

const Colors = []string{"red", "green"} // slice
const Started = time.Now()              // function call
./main.go:9:16: []string{…} (value of type []string) is not constant
./main.go:10:13: time.Now() (value of struct type time.Time) is not constant

Por qué Go no tiene slices ni maps constantes

Los slices, los maps y los structs que los contienen son referencias a memoria que existe en tiempo de ejecución, así que el compilador no puede incrustarlos en el programa como valores fijos, y Go no tiene un modificador readonly ni final para variables. Las alternativas habituales:

La copia cuesta una reserva de memoria por llamada, lo cual está bien para datos del tamaño de una configuración. Para búsquedas por clave, un switch dentro de una función es otra opción que se comporta como una constante: func statusText(code int) string { switch code { ... } }.

Constantes sin tipo

Una constante declarada sin tipo es sin tipo (untyped). Tiene una clase (entero, flotante, rune, string, bool) pero ningún tipo Go concreto hasta que se usa, y se adapta al contexto:

Ratio funciona como int, float64, uint8 y float32 sin ninguna conversión. Por eso compila time.Sleep(2 * time.Second): 2 no tiene tipo y se convierte en un time.Duration.

Cuando el contexto no exige un tipo, como en x := Ratio, la constante recibe su tipo por defecto:

Clase de constante sin tipoTipo por defecto
entero (42)int
punto flotante (4.2)float64
rune ('a')rune (int32)
complejo (2i)complex128
stringstring
booleanobool

Aritmética exacta

Las constantes numéricas sin tipo son exactas. El compilador representa los enteros con al menos 256 bits, así que los valores intermedios pueden ser mucho mayores que cualquier tipo de Go:

Huge no se puede imprimir como entero, porque pasarla a fmt.Println la convierte en int, y el compilador lo detecta (float64(Huge) sí funciona, porque un flotante puede contener esa magnitud):

cannot use Huge (untyped int constant 1267650600228229401496703205376) as int value in argument to fmt.Println (overflows)

La misma comprobación detiene errores más pequeños en tiempo de compilación, como var b byte = 300:

cannot use 300 (untyped int constant) as byte value in variable declaration (overflows)

Constantes con tipo

Si le das un tipo a una constante, se comporta como un valor de ese tipo en todas partes, incluida la negativa de Go a mezclar tipos:

const Limit int = 10

var f float64 = 2
fmt.Println(Limit * f)
invalid operation: Limit * f (mismatched types int and float64)

Con const Limit = 10 (sin tipo), Limit * f compila y da 20. Así que deja las constantes sin tipo salvo que el tipo aporte significado. Lo aporta cuando declaras constantes de un tipo con nombre propio, que es como Go construye los enums:

type Weekday int

const (
	Sunday Weekday = iota
	Monday
	Tuesday
)

Aquí el tipo es lo importante: una función que recibe un Weekday documenta lo que espera. iota y los patrones de enum basados en él se explican en la página de enums e iota.

const frente a var

constvar
Puede cambiarno
Valor conocidoen tiempo de compilaciónen tiempo de ejecución
Tipos permitidosbool, numéricos, stringcualquiera
Ocupa memoria en ejecuciónno
Se puede tomar su dirección (&x)no
Declararla sin usarla es un errornosí, para las locales

Usa const para todo lo que sea realmente fijo: límites, tamaños, nombres, códigos de protocolo, cadenas de formato. Obtienes gratis comprobaciones de desbordamiento en tiempo de compilación y aritmética exacta.

Trampas

Las constantes con tipo no se adaptan. const Timeout int = 5 no se puede pasar donde se espera un time.Duration sin una conversión; una const Timeout = 5 sin tipo sí se puede multiplicar: Timeout * time.Second.

La división entera ocurre con constantes enteras. const Half = 1 / 2 vale 0, porque los dos operandos son enteros sin tipo. Escribe 1.0 / 2 para obtener 0.5.

Sin dirección. &MaxRetries no compila. Si una API quiere un *int, copia antes la constante en una variable.

Preguntas frecuentes

¿Cómo se declara una constante en Go?

Con const: const MaxRetries = 3 o, con un tipo explícito, const Timeout time.Duration = 5 * time.Second. Agrupa varias en un bloque: const ( A = 1; B = 2 ). El valor tiene que poder calcularse en tiempo de compilación.

¿Puedo crear un slice, map o array constante en Go?

No. Las constantes solo pueden ser booleanos, números (runes incluidos) y strings. const Colors = []string{"red"} falla con is not constant. Usa una var a nivel de paquete y, si quien la usa no debe modificarla, expón una función que devuelva una copia nueva.

¿Qué es una constante sin tipo en Go?

Una constante declarada sin tipo, como const Pi = 3.14159. No tiene un tipo fijo hasta que se usa, así que la misma constante funciona como float32, como float64 o, si su valor lo permite, como int. Las constantes sin tipo también son exactas: el compilador mantiene al menos 256 bits de precisión, así que const Big = 1 << 100 es válida siempre que solo la uses en expresiones cuyo resultado quepa.

¿Qué diferencia hay entre const y var en Go?

Una const se fija en tiempo de compilación y nunca puede cambiar; no ocupa memoria en tiempo de ejecución y solo puede contener un bool, un número o un string. Una var es una posición de memoria que se puede reasignar y puede contener cualquier tipo, incluidos valores calculados en tiempo de ejecución como time.Now().

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR