In Go, for range ripete un blocco di codice per i valori di un'espressione range.
L'espressione range determina se ogni iterazione produrrà uno o due valori.
range su uno slice restituisce l'indice e il valore di ogni elemento, in ordine:
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30
range su una mappa restituisce ogni chiave e il suo valore, ma l'ordine di iterazione non è garantito.
Go randomizza deliberatamente l'ordine di iterazione delle mappe, quindi lo stesso programma può produrre output diversi a ogni esecuzione.
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 su una stringa restituisce l'indice di byte e ogni rune (punto di codice Unicode).
Nell'esempio seguente, 子 occupa tre byte, quindi 猫 inizia all'indice di byte 3, non 1.
for i, r := range "子猫" {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 3 29483 猫
Se invece ti servono gli indici delle rune, converti la stringa in uno slice di rune:
for i, r := range []rune("子猫") {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 1 29483 猫
range può iterare direttamente su un intero, restituendo valori da 0 fino a quel numero escluso.
Lo zero e i valori negativi sono validi, ma non producono alcuna iterazione.
for n := range 3 {
fmt.Println(n)
}
// 0
// 1
// 2
range accetta un iteratore di tipo iter.Seq[V] o iter.Seq2[K, V].
Un iteratore è una funzione che produce una sequenza di valori, uno alla volta.
range può quindi scorrerli.
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
Infine, range può ricevere i valori inviati attraverso un channel finché quel channel non viene chiuso altrove.
I channel sono trattati più in dettaglio più avanti nel programma del track.
Go non compila se una variabile viene dichiarata ma mai usata.
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(v)
}
// Go build failed: declared and not used: i
Se serve solo il valore, assegna l'indice o la chiave a _ per ignorarlo.
vals := []int{10, 20, 30}
for _, v := range vals {
fmt.Println(v)
}
// 10
// 20
// 30
Se serve solo l'indice, omettilo del tutto:
vals := []int{10, 20, 30}
for i := range vals {
fmt.Println(i)
}
// 0
// 1
// 2
Se non servono né l'indice né il valore, puoi ometterli entrambi:
vals := []int{10, 20, 30}
count := 0
for range vals {
count++
}
// count == 3