En Go, tienes dos formas principales de crear variables: la declaración formal con var y la declaración corta con :=. La primera es la más explícita y te permite decirle al compilador exactamente qué tipo de dato quieres, incluso si aún no tienes un valor asignado. Cuando declaras una variable sin un valor inicial, como var x int, Go le asigna automáticamente un zero value (en este caso, 0), lo que garantiza que la variable esté lista para usarse y no contenga basura de la memoria. También puedes ser explícito con el valor, como en var x int = 5.
:= es la “declaración corta” (short declaration). Es un atajo que combina la declaración y la asignación, permitiendo que el compilador infiera el tipo de dato automáticamente basándose en el valor que le entregas a la derecha. Es la herramienta que más usarás dentro de tus funciones para mantener el código limpio, pero tiene reglas estrictas: solo puedes usarla dentro de funciones y no puedes usarla a nivel de package (fuera de las funciones); para variables globales, el uso de var es obligatorio.
Debes usar var cuando declares variables que se inicializarán más tarde, cuando necesites que empiecen con su valor por defecto, o cuando la legibilidad exija que el tipo sea evidente. Usa := para variables locales donde el valor es conocido inmediatamente.
El mayor riesgo de usar := es el shadowing (sombreado). Si usas := dentro de un bloque con un alcance limitado, como un if o un for, y usas el mismo nombre que una variable declarada afuera, no estarás actualizando la variable original, sino creando una nueva variable “escondida” que solo vive dentro de ese bloque. Esto hará que, al salir del bloque, la variable original parezca no haber cambiado, provocando errores lógicos muy difíciles de detectar.
package main
import "fmt"
// Usamos 'var' para variables a nivel de paquete.
// El operador ':=' no es válido aquí.
var impuesto float64 = 0.21
func main() {
// Declaramos una variable sin valor inicial.
// Go le asigna su "zero value" (0.0 para float64).
var subtotal float64
// Declaración corta: Go infiere que 'precio' es float64.
precio := 100.0
// Declaración explícita con tipo y valor.
var cantidad int = 5
// Calculamos el subtotal y el total.
// Usamos ':=' porque estamos creando 'total' por primera vez en este scope.
subtotal = precio * float64(cantidad)
total := subtotal * (1 + impuesto)
fmt.Printf("Subtotal: %.2f, Total con impuesto: %.2f\n", subtotal, total)
// --- El peligro del shadowing (sombreado) ---
total := 500.0 // Creamos una nueva 'total' local
if true {
// ¡ERROR COMÚN! El ':=' aquí crea una NUEVA variable llamada 'total'
// que solo existe dentro de este bloque 'if'.
total := 10.0
fmt.Println("Dentro del if (variable sombreada):", total)
}
// Al salir del if, volvemos a la 'total' de arriba, que sigue siendo 500.0
fmt.Println("Fuera del if (variable original):", total)
}
Análisis del código
En el ejemplo, empezamos con impuesto declarada con var fuera de main, lo cual es necesario porque := no funciona a nivel de paquete.
Dentro de main, subtotal se declara con var sin asignarle nada; gracias al zero value de Go, sabemos que empieza en 0.0 sin riesgo de errores. En cambio, para precio, usamos := porque ya conocemos su valor (100.0) y no necesitamos escribir float64 explícitamente, ahorrándonos ruido visual.
La parte crítica es el bloque final. Observa cómo declaramos total := 500.0. Cuando entramos al if, la línea total := 10.0 usa el operador :=. Esto no actualiza la variable de 500.0 a 10.0; lo que hace es crear una variable nueva que se llama igual y “tapa” a la anterior mientras estemos dentro de las llaves { ... }. Por eso, cuando el programa sale del if, la variable total que imprimimos al final es la original, la de 500.0.
El error frecuente
El error más común ocurre cuando intentas actualizar una variable existente dentro de un bloque usando := en lugar de =.
package main
import "fmt"
func main() {
contador := 0
if true {
// ERROR: Esto crea una nueva variable 'contador' local.
// No actualiza la variable de arriba.
contador := 1
fmt.Println("Contador interno:", contador) // Imprime 1
}
// El valor original no cambió.
fmt.Println("Contador externo:", contador) // Imprime 0
}
Si tu intención es modificar el valor de una variable ya declarada, usa siempre el operador de asignación = sin el signo de exclamación.
N° 24