Los operadores aritméticos en Go son símbolos binarios y unarios que permiten ejecutar operaciones matemáticas sobre operandos de tipos numéricos, incluyendo enteros, de punto flotante y complejos. A diferencia de otros lenguajes de la familia C, Go impone una disciplina estricta de tipado donde no existe la promoción implícita de tipos (coerción); los operandos deben poseer el mismo underlying type para que la operación sea válida en tiempo de compilación. Esta restricción elimina errores comunes de precisión y desbordamientos silenciosos, obligando al desarrollador a realizar conversiones explícitas cuando se trabaja con precisiones distintas como int32 y int64.
El conjunto de operadores incluye la suma (+), resta (-), multiplicación (*), división (/) y residuo (%). Mientras que los primeros cuatro están disponibles para todos los tipos numéricos, el operador de residuo está restringido exclusivamente a tipos enteros. En el caso de los enteros, la división trunca cualquier parte fraccionaria hacia cero, un comportamiento crítico para entender la aritmética de tipos y la manipulación de índices en estructuras de datos.
package main
import "fmt"
func main() {
var a int32 = 10
var b int64 = 20
// c := a + b // Error: invalid operation (mismatched types int32 and int64)
// Aritmética de tipos con conversión explícita
sum := int64(a) + b
fmt.Println(sum) // → 30
// División de enteros: truncamiento hacia cero
fmt.Println(7 / 3) // → 2
fmt.Println(-7 / 3) // → -2
}
GoEl aspecto más contraintuitivo de la división entera es que el resultado es siempre un entero del mismo tipo que los operandos. Si se requiere una división con decimales, al menos uno de los operandos debe ser una constante sin tipo (untyped constant) con punto flotante o un valor de tipo float32 o float64.
Comportamiento del operador residuo con operandos negativos
La especificación de Go define que el operador residuo (%) para los operandos x e y debe satisfacer la identidad matemática (x / y) * y + x % y == x. Dado que la división entera en Go siempre trunca hacia cero, el signo del resultado del residuo está determinado estrictamente por el signo del dividendo (x), independientemente del signo del divisor (y). Esto diferencia a Go de lenguajes o librerías donde el módulo siempre devuelve un valor positivo.
Este comportamiento es predecible y consistente con la arquitectura de la mayoría de las CPUs modernas, pero requiere atención especial cuando se implementan algoritmos circulares o de rotación de índices que involucran decrementos. Si el dividendo es negativo, el resultado será negativo o cero, lo que podría invalidar accesos a arreglos si no se normaliza el resultado sumando el divisor.
package main
import "fmt"
func main() {
// Residuo con dividendo negativo
fmt.Println(-7 % 3) // → -1 (porque -7/3 es -2, y -2*3 + (-1) == -7)
// Residuo con divisor negativo
fmt.Println(7 % -3) // → 1 (porque 7/-3 es -2, y -2*-3 + 1 == 7)
// Residuo con ambos negativos
fmt.Println(-7 % -3) // → -1 (porque -7/-3 es 2, y 2*-3 + (-1) == -7)
}
GoUn desbordamiento (overflow) en operaciones aritméticas con enteros en Go no genera un panic en tiempo de ejecución; en su lugar, el valor simplemente “da la vuelta” siguiendo las reglas del complemento a dos. Sin embargo, el compilador sí detectará y bloqueará desbordamientos en expresiones constantes que puedan ser evaluadas durante la fase de compilación.
Truncamiento hacia cero y la identidad del residuo
El mecanismo interno por el cual Go gestiona el residuo asegura que la relación entre cociente y resto sea siempre íntegra bajo la aritmética de enteros del lenguaje. En otros entornos de programación, el término “módulo” y “residuo” se usan indistintamente, pero en Go la distinción es técnica: % es el operador de residuo de una división truncada.
Un edge case real ocurre cuando se intenta realizar la operación x % y donde y es cero. En este escenario, el runtime de Go disparará un runtime panic: integer divide by zero. A diferencia de las operaciones de punto flotante, donde la división por cero resulta en NaN o Inf según el estándar IEEE 754, la aritmética entera es implacable y detendrá la ejecución si no se valida el divisor previamente.
- Módulo: Léxico y Sintaxis Fundamental
- Artículo número: #4