Literales Numéricos en Go: Binario, Hex, Octal y Floats

Los literales numéricos en Go son representaciones léxicas que definen valores constantes enteros o de punto flotante directamente en el código fuente mediante un conjunto de prefijos y reglas de notación estandarizadas. Estas constantes carecen de un tipo específico (untyped) hasta que el compilador las asigna a una variable o las evalúa en un contexto que requiere un tipo concreto, permitiendo una flexibilidad superior en operaciones aritméticas iniciales.

A partir de la versión 1.13, Go modernizó su sintaxis para alinearse con las necesidades de la programación de sistemas y la legibilidad del desarrollador. Este comportamiento resuelve la ambigüedad histórica de las representaciones octales y facilita la manipulación de datos a nivel de bit y configuraciones de memoria. Al introducir prefijos explícitos y separadores visuales, el lenguaje elimina la carga cognitiva de interpretar valores densos, mejorando la mantenibilidad sin introducir costos de rendimiento en el binario final, ya que todas las transformaciones ocurren durante la fase de análisis léxico.

Bases enteras y legibilidad con separadores

La especificación del lenguaje permite definir enteros en cuatro bases principales utilizando prefijos específicos. La base binaria se declara mediante 0b o 0B, la octal con 0o o 0O, y la hexadecimal mediante el tradicional 0x o 0X. Si no existe prefijo, el literal se interpreta como decimal. Es relevante notar que, aunque la notación octal antigua (un cero a la izquierda como 0755) sigue siendo válida por compatibilidad, la forma explícita 0o755 es la preferida por la comunidad para evitar errores de interpretación.

Para gestionar cifras de gran magnitud o segmentar bytes en representaciones binarias, Go permite el uso del guion bajo (_) como separador de dígitos. Este carácter es puramente cosmético para el desarrollador; el lexer lo ignora completamente tras validar su posición. Su implementación permite separar grupos de miles en decimales o nibbles en hexadecimal, facilitando la auditoría visual de máscaras de bits y constantes físicas.

En el ámbito de los números de punto flotante, Go soporta tanto la notación decimal estándar como la notación científica. Esta última utiliza el sufijo e o E seguido de un exponente decimal. Adicionalmente, el lenguaje permite literales de punto flotante en hexadecimal (0x), donde el exponente se indica con la letra p o P y representa una potencia de 2 en lugar de 10, lo cual es fundamental para representar con exactitud valores IEEE 754.

package main

import "fmt"

func main() {
	// Enteros en distintas bases con separadores
	decimal := 1_000_000
	binario := 0b0101_1101 // Representación de un byte (93 decimal)
	octal   := 0o755       // Permisos de archivo (493 decimal)
	hex     := 0x1A_2B_3C  // Dirección o valor hex (1715004 decimal)

	// Punto flotante y notación científica
	poblacion := 8.2e9      // 8.2 * 10^9
	nano      := 1.234e-10  // 1.234 * 10^-10
	
	// Hexadecimal floating-point literal
	// 0x1p-2 representa 1.0 * 2^-2 = 0.25
	hexFloat := 0x1.0p-2 

	fmt.Printf("Binario: %d\n", binario)
	fmt.Printf("Científica: %f\n", poblacion)
	fmt.Printf("Hex Float: %f\n", hexFloat) // → 0.250000
}
Go

El uso del separador _ no está permitido entre el prefijo y el primer dígito (por ejemplo, 0b_0101 es inválido). Su propósito es segmentar valores, no prefijos, lo que obliga a una estructura de tokenización estricta.

Restricciones sintácticas del separador de dígitos

El lexer de Go impone reglas de adyacencia sumamente estrictas para garantizar que la legibilidad no se convierta en una fuente de confusión o errores de escaneo.

Reglas de adyacencia del separador de dígitos

Un guion bajo solo puede aparecer entre dígitos. No se permite su uso al inicio del literal, al final del mismo, ni de forma consecutiva (por ejemplo, 1__000 es ilegal). En los literales de punto flotante, el separador no puede situarse inmediatamente después del punto decimal ni antes/después del marcador de exponente (e, p). Estas restricciones aseguran que el separador siempre actúe como un divisor interno y nunca como parte de la semántica del valor o del prefijo del sistema numérico. El incumplimiento de estas reglas genera un error de compilación inmediato con el mensaje invalid use of _ in numeric literal.


  • Módulo: Léxico y Sintaxis Fundamental
  • Artículo número: #12

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio