Variantes del bucle for y semántica de range
Go expresa cada bucle con for, pero la forma que elijas cambia lo que copias, lo que puedes mutar y cuándo se detiene el bucle.
Busca en todas las páginas de la documentación
Go expresa cada bucle con for, pero la forma que elijas cambia lo que copias, lo que puedes mutar y cuándo se detiene el bucle.
Esta página mapea cada variante de for a las colecciones y canales que verás en el código de producción.
La cabecera for de tres partes cubre los bucles contados.
La forma solo con condición actúa como while.
for range recorre slices, arrays, mapas, canales y cadenas con un significado de índice/valor específico del tipo.
Los canales se bloquean hasta que llega un valor o el canal se cierra.
Los mapas iteran en orden aleatorio.
Las cadenas devuelven desplazamientos de bytes y runes, no bytes directamente.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
package main
import "fmt"
func main() {
// Estilo C
for i := 0; i < 3; i++ {
fmt.Println("count", i)
}
// Estilo while
n := 3
for n > 0 {
n--
}
// range slice
for i, v := range []int{10, 20} {
fmt.Println(i, v)
}
}Cuándo usar esto:
for de tres partes cuando necesites un contador de índice con una condición final clara.for solo con condición para bucles de eventos, reintentos y bombas de canal (for { select { ... } }).for range para iteración idiomática sobre colecciones y canales abiertos.for range en lugar de alternativas 1..n a través de slices o for i := 0; i < n; i++ - Go no tiene un operador de rango inclusivo.package main
import (
"fmt"
"time"
)
func main() {
// Slice: mutar por índice
nums := []int{1, 2, 3}
for i := range nums {
nums[i] *= 2
}
fmt.Println("slice", nums)
// Map: claves y valores (el orden varía en cada ejecución)
m := map[string]int{"a": 1, "b": 2}
for k, v := range m {
fmt.Println("map", k, v)
}
// Channel: recibir hasta que se cierre
ch := make(chan int, 2)
ch <- 1
ch <- 2
close(ch)
for v := range ch {
fmt.Println("chan", v)
}
// String: índice de bytes y rune
for i, r := range "Go🙂" {
fmt.Printf("string i=%d r=%U\n", i, r)
}
// Bucle infinito con interrupción por tiempo límite
deadline := time.Now().Add(50 * time.Millisecond)
for {
if time.Now().After(deadline) {
break
}
}
fmt.Println("done")
}Lo que esto demuestra:
for range en un canal termina cuando el canal se cierra y se vacían los valores.range de cadenas decodifica runes UTF-8; el índice salta por el ancho de bytes para caracteres multibyte.break, return, o select.for crea un ámbito de bloque; la variable de inicialización en un bucle de tres partes tiene el ámbito de la sentencia for.range evalúa la colección una vez; para arrays/slices copia la cabecera, no los elementos del array subyacente.for range se bloquea hasta que un valor está listo; el patrón de valor cero más ok es implícito en la forma range.range de cadenas convierte bytes a runes; len(s) es la longitud en bytes, que difiere del recuento de runes.| Tipo | Índice (1er valor) | Valor (2do valor) | Notas |
|---|---|---|---|
| Slice / array | índice int | copia del elemento | mutar con s[i], no v |
| Map | copia de clave | copia de valor | orden aleatorizado |
| Channel | (ninguno) | elemento recibido | termina después de cerrar + vaciar |
| String | desplazamiento de bytes | rune (int32) | el desplazamiento avanza por el ancho UTF-8 |
| Forma | Sintaxis | Uso típico |
|---|---|---|
| Tres partes | for i := 0; i < n; i++ | bucles contados |
| Solo condición | for cond | estilo while, leer hasta EOF |
| Infinito | for { } | servidores, bucles select |
| Range | for k, v := range x | colecciones, canales, cadenas |
// Omite el valor o el índice con el identificador en blanco
for _, v := range items { _ = v }
for i := range items { _ = i }
// range sobre array copia elementos para la forma de valor en arrays grandes - usa índice
var big [10000]byte
for i := range big {
big[i] = 1
}for _, v := range s { v = 1 } actualiza una copia. Solución: usa el índice: for i := range s { s[i] = 1 }.for range ch se bloquea para siempre. Solución: cierra desde el lado del remitente o usa select con ctx.Done().len("é") son 2 bytes en UTF-8. Solución: usa range o utf8.RuneCountInString.<= cuando se pretendía <. Solución: prefiere los modismos for i := 0; i < len(s); i++.| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
for range | Iteración idiomática | Necesitas iteración inversa sin matemáticas de índice adicionales |
Índice for i := 0; ... | Necesitas el elemento anterior/siguiente por índice | Un simple bucle range es suficiente |
slices.Backward / índice manual | Recorrido inverso | El range hacia adelante es suficiente |
for { select } | Multiplexar canales y temporizadores | Recorrido de una sola colección |
| Iteradores de la biblioteca estándar (Go 1.23+) | Secuencias personalizadas con yield | Simples recorridos de slice/map |
No - for condition { } es la forma while.
La palabra clave es siempre for.
Sí - ambos son no-ops con cero iteraciones.
Un mapa nil sigue siendo irrecuperable para asignación sin make.
Go aleatoriza el inicio de la iteración del mapa para evitar la dependencia del orden.
Ordena las claves cuando necesites una salida determinista.
Después de que el canal se cierra y se reciben todos los valores en búfer.
Un canal abierto se bloquea para siempre en la siguiente recepción.
El valor es una copia - costoso para structs grandes.
Usa el índice o un slice de punteros []*T cuando el perfilado muestre el costo de la copia.
Usa for i := 0; i < n; i++.
No hay for i := range n en Go antiguo; Go 1.22+ permite for i := range n cuando n es un entero.
Itera i de 0 a n-1 cuando n es un tipo de entero no negativo.
Útil para bucles contados sin inicialización/post-procesamiento manual.
Sí - eliminar la clave actual es seguro.
Eliminar otras claves durante la iteración sigue la semántica del mapa; mantén la lógica simple.
Usa break en una etiqueta o return de la función.
break solo sale del select, no del for circundante.
Decodifica UTF-8, lo que cuesta más que los escaneos de bytes brutos.
Para datos solo ASCII, accede directamente a los bytes con comprobaciones de límites.
for y rangeVersiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, go fix modernizers - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación), y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 18 jul 2026