En Go, for range repite un bloque de código para los valores de una expresión de range.
La expresión de range determina si cada iteración producirá uno o dos valores.
range sobre un slice produce el índice y el valor de cada elemento en orden:
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30
range sobre un mapa produce cada clave y valor, pero el orden de iteración no está garantizado.
Go aleatoriza deliberadamente el orden de iteración de los mapas, por lo que el mismo programa puede producir una salida diferente en cada ejecución.
hash := map[int]int{9: 10, 99: 20, 999: 30}
for k, v := range hash {
fmt.Println(k, v)
}
// 99 20
// 999 30
// 9 10
range sobre un string produce el índice de byte y cada runa (punto de código Unicode).
En el siguiente ejemplo, 子 ocupa tres bytes, así que 猫 comienza en el índice de byte 3, no en 1.
for i, r := range "子猫" {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 3 29483 猫
Si necesitas índices de runas en su lugar, convierte el string a un slice de runas:
for i, r := range []rune("子猫") {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 1 29483 猫
range puede iterar sobre un entero directamente, produciendo valores desde 0 hasta el entero, pero sin incluirlo.
Los valores cero y negativos son válidos, pero no producen ninguna iteración.
for n := range 3 {
fmt.Println(n)
}
// 0
// 1
// 2
range acepta un iterador de tipo iter.Seq[V] o iter.Seq2[K, V].
Un iterador es una función que produce una secuencia de valores uno a la vez.
range puede entonces recorrer esos valores.
text := "The quick brown fox"
for word := range strings.FieldsSeq(text) {
fmt.Println(word)
}
// The
// quick
// brown
// fox
names := []string{"Alice", "Bob", "Vera"}
for i, v := range slices.All(names) {
fmt.Println(i, ":", v)
}
// 0 : Alice
// 1 : Bob
// 2 : Vera
Por último, range puede recibir valores enviados a través de un canal hasta que ese canal se cierre en otro lugar.
Los canales se explican con más detalle más adelante en el temario del track.
Go no compila si se declara una variable pero nunca se usa.
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(v)
}
// Go build failed: declared and not used: i
Si solo se necesita el valor, asigna el índice o la clave a _ para ignorarlo.
vals := []int{10, 20, 30}
for _, v := range vals {
fmt.Println(v)
}
// 10
// 20
// 30
Si solo se necesita el índice, omítelo por completo:
vals := []int{10, 20, 30}
for i := range vals {
fmt.Println(i)
}
// 0
// 1
// 2
Si no se necesita ni el índice ni el valor, se pueden omitir ambos:
vals := []int{10, 20, 30}
count := 0
for range vals {
count++
}
// count == 3