Variables de bucle seguras
Go garantiza que cada iteración de un bucle for crea una nueva variable de iteración. Esto elimina un error clásico al capturar variables en goroutines o closures:

nombres := []string{"Ana", "Luis", "Marta"}
for _, nombre := range nombres {
go func() {
fmt.Println(nombre) // cada goroutine captura su propia copia
}()
}
Cada goroutine captura su propia variable nombre, por lo que se imprimen los tres nombres correctamente (en cualquier orden). Este comportamiento es especialmente importante al lanzar goroutines o pasar funciones como callbacks dentro de bucles.
Las variables de iteración son independientes en cada ciclo del bucle. No es necesario crear copias manuales como
n := nombredentro del bucle.
Range sobre enteros
Go permite iterar directamente sobre un rango de enteros con for range, lo que simplifica los bucles de conteo:
// Iterar de 0 a 4
for i := range 5 {
fmt.Print(i, " ") // 0 1 2 3 4
}
// Sin variable de iteración
for range 10 {
fmt.Println("Repetición")
}
// Útil para inicializar colecciones
workers := make([]Worker, 0, 10)
for range 10 {
workers = append(workers, NuevoWorker())
}
Esta sintaxis es más concisa y menos propensa a errores que el bucle clásico for i := 0; i < n; i++.
Iteradores con range-over-func
Go soporta el uso de for range sobre funciones iteradoras que siguen las firmas del paquete iter. Esto permite crear generadores y secuencias perezosas que se consumen con la misma sintaxis que slices y mapas.
Tipos de iteradores
import "iter"
// iter.Seq[V] — secuencia de un valor por iteración
// iter.Seq2[K, V] — secuencia de dos valores por iteración
Crear un iterador personalizado
// Generador de números de Fibonacci
func fibonacci() iter.Seq[int] {
return func(yield func(int) bool) {
a, b := 0, 1
for {
if !yield(a) {
return // el consumidor llamó a break
}
a, b = b, a+b
}
}
}
// Consumir con for range
for n := range fibonacci() {
if n > 1000 {
break
}
fmt.Print(n, " ")
}
// 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
La función yield produce un valor y devuelve false si el consumidor ha dejado de iterar (por ejemplo, con break). Este patrón permite crear secuencias infinitas de forma segura.
Iteradores en la biblioteca estándar
Los paquetes slices y maps exponen iteradores que se combinan con for range:
import (
"maps"
"slices"
)
numeros := []int{10, 20, 30, 40, 50}
// slices.All: devuelve índice y valor
for i, v := range slices.All(numeros) {
fmt.Printf("[%d]=%d ", i, v)
}
// slices.Values: devuelve solo valores
for v := range slices.Values(numeros) {
fmt.Print(v, " ")
}
// maps.Keys y maps.Values
catalogo := map[string]float64{"teclado": 59.99, "ratón": 25.50}
for clave := range maps.Keys(catalogo) {
fmt.Println(clave)
}
Iteradores Seq2 personalizados
func elementosConIndice[T any](items []T) iter.Seq2[int, T] {
return func(yield func(int, T) bool) {
for i, item := range items {
if !yield(i, item) {
return
}
}
}
}
palabras := []string{"hola", "mundo", "go"}
for i, p := range elementosConIndice(palabras) {
fmt.Printf("%d: %s\n", i, p)
}
Los iteradores son una abstracción que unifica el acceso a secuencias, ya sean finitas o infinitas. Utiliza
iter.Seqcuando necesites producir valores bajo demanda sin materializar toda la colección en memoria.
Números aleatorios: math/rand/v2
El paquete math/rand/v2 ofrece una API simplificada con algoritmos modernos (ChaCha8, PCG) que no requiere inicialización manual de semilla:
import "math/rand/v2"
// API simplificada
n := rand.IntN(100) // entero en [0, 100)
f := rand.Float64() // flotante en [0.0, 1.0)
b := rand.Int64() // int64 aleatorio
// Permutar un slice
elementos := []string{"a", "b", "c", "d", "e"}
rand.Shuffle(len(elementos), func(i, j int) {
elementos[i], elementos[j] = elementos[j], elementos[i]
})
// Generador con fuente determinista (útil para pruebas)
fuente := rand.NewPCG(42, 0)
rng := rand.New(fuente)
fmt.Println(rng.IntN(100)) // siempre el mismo resultado para la semilla 42
Herramientas de desarrollo con go tool
Go permite declarar y gestionar herramientas de desarrollo directamente en go.mod, garantizando que todos los desarrolladores del proyecto usen las mismas versiones:
# Añadir herramientas al módulo
go get -tool golang.org/x/tools/cmd/stringer@latest
go get -tool github.com/golangci/golangci-lint/cmd/golangci-lint@latest
El go.mod incluye una sección tool:
tool (
golang.org/x/tools/cmd/stringer
github.com/golangci/golangci-lint/cmd/golangci-lint
)
Ejecutar una herramienta:
go tool stringer -type=Direction ./...
go tool golangci-lint run
Las herramientas declaradas en
go.modse versionan junto con el código del proyecto. Esto elimina la necesidad de scripts de instalación separados y garantiza reproducibilidad en el equipo y en CI/CD.
Punteros débiles: el paquete weak
El paquete weak permite crear punteros débiles que no impiden la recolección de basura. Son útiles para implementar caches en aplicaciones de larga ejecución:
import "weak"
type Cache struct {
datos map[string]weak.Pointer[[]byte]
}
func (c *Cache) Obtener(clave string) ([]byte, bool) {
if ptr, ok := c.datos[clave]; ok {
if val := ptr.Value(); val != nil {
return *val, true
}
// El GC recolectó el valor: eliminamos la entrada muerta
delete(c.datos, clave)
}
return nil, false
}
Los punteros débiles mantienen una referencia que no cuenta para el recolector de basura. Si no hay otras referencias fuertes al objeto, el GC puede recolectarlo y el puntero débil devolverá nil.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Go es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Go
Explora más contenido relacionado con Go y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Comprender la semántica de variables de bucle por iteración. Usar for range sobre enteros. Crear y consumir iteradores con iter.Seq e iter.Seq2. Generar números aleatorios con math/rand/v2. Gestionar herramientas de desarrollo con go tool.