Em Go, for range repete um bloco de código para os valores de uma expressão de range.
A expressão de range determina se cada iteração vai produzir um valor ou dois.
range sobre um slice produz o índice e o valor de cada elemento, em ordem:
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30
range sobre um map produz cada chave e cada valor, mas a ordem da iteração não é garantida.
Go embaralha de propósito a ordem de iteração dos maps, então o mesmo programa pode produzir uma saída diferente a cada execução.
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 uma string produz o índice em bytes e cada rune (ponto de código Unicode).
No exemplo a seguir, 子 ocupa três bytes, então 猫 começa no índice de byte 3, e não em 1.
for i, r := range "子猫" {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 3 29483 猫
Se você precisar de índices de runes, converta a string em um slice de runes:
for i, r := range []rune("子猫") {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 1 29483 猫
range pode iterar diretamente sobre um número inteiro, produzindo valores de 0 até, mas sem incluir, esse número inteiro.
O valor zero e os valores negativos são válidos, mas não geram nenhuma iteração.
for n := range 3 {
fmt.Println(n)
}
// 0
// 1
// 2
range aceita um iterador do tipo iter.Seq[V] ou iter.Seq2[K, V].
Um iterador é uma função que produz uma sequência de valores, um de cada vez.
O range pode então percorrer esses 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 fim, o range pode receber valores enviados por um canal até que esse canal seja fechado em outro lugar.
Os canais são abordados com mais profundidade mais adiante no programa da trilha.
Go não compila se uma variável for declarada e nunca usada.
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(v)
}
// Go build failed: declared and not used: i
Se você só precisar do valor, atribua o índice ou a chave a _ para ignorá-lo.
vals := []int{10, 20, 30}
for _, v := range vals {
fmt.Println(v)
}
// 10
// 20
// 30
Se você só precisar do índice, omita o valor por completo:
vals := []int{10, 20, 30}
for i := range vals {
fmt.Println(i)
}
// 0
// 1
// 2
Se você não precisar nem do índice nem do valor, os dois podem ser omitidos:
vals := []int{10, 20, 30}
count := 0
for range vals {
count++
}
// count == 3