Στη Go, το for range επαναλαμβάνει ένα μπλοκ κώδικα για τις τιμές που παράγει μια έκφραση range.
Η έκφραση range καθορίζει αν κάθε επανάληψη θα δίνει μία τιμή ή δύο.
Το range πάνω σε ένα slice δίνει τη θέση και την τιμή κάθε στοιχείου με τη σειρά:
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30
Το range πάνω σε ένα map δίνει κάθε κλειδί και τιμή, αλλά η σειρά της επανάληψης δεν είναι εγγυημένη.
Η Go τυχαιοποιεί σκόπιμα τη σειρά επανάληψης των map, οπότε το ίδιο πρόγραμμα μπορεί να παράγει διαφορετική έξοδο σε κάθε εκτέλεση.
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 πάνω σε ένα string δίνει τη θέση του byte και κάθε rune (σημείο κώδικα Unicode).
Στο παρακάτω παράδειγμα, το 子 καταλαμβάνει τρία bytes, οπότε το 猫 ξεκινά στη θέση byte 3, όχι 1.
for i, r := range "子猫" {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 3 29483 猫
Αν χρειάζεσαι θέσεις rune, μετέτρεψε το string σε slice από rune:
for i, r := range []rune("子猫") {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 1 29483 猫
Το range μπορεί να κάνει επανάληψη απευθείας πάνω σε έναν ακέραιο, δίνοντας τιμές από το 0 μέχρι αλλά χωρίς να συμπεριλαμβάνεται ο ίδιος ο ακέραιος.
Το μηδέν και οι αρνητικές τιμές είναι έγκυρες, αλλά δεν παράγουν καμία επανάληψη.
for n := range 3 {
fmt.Println(n)
}
// 0
// 1
// 2
Το range δέχεται έναν iterator τύπου iter.Seq[V] ή iter.Seq2[K, V].
Ένας iterator είναι μια συνάρτηση που παράγει μια ακολουθία τιμών, μία κάθε φορά.
Το range μπορεί στη συνέχεια να διατρέξει αυτές τις τιμές.
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
Τέλος, το range μπορεί να λαμβάνει τιμές που στέλνονται μέσα από ένα κανάλι, μέχρι αυτό το κανάλι να κλείσει κάπου αλλού.
Τα κανάλια καλύπτονται με περισσότερες λεπτομέρειες αργότερα στην ύλη της διαδρομής.
Η Go δεν θα μεταγλωττίσει αν μια μεταβλητή δηλωθεί αλλά δεν χρησιμοποιηθεί ποτέ.
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(v)
}
// Go build failed: declared and not used: i
Αν χρειάζεσαι μόνο την τιμή, ανάθεσε τη θέση ή το κλειδί στο _ για να το αγνοήσεις.
vals := []int{10, 20, 30}
for _, v := range vals {
fmt.Println(v)
}
// 10
// 20
// 30
Αν χρειάζεσαι μόνο τη θέση, παράλειψέ την εντελώς:
vals := []int{10, 20, 30}
for i := range vals {
fmt.Println(i)
}
// 0
// 1
// 2
Αν δεν χρειάζεσαι ούτε τη θέση ούτε την τιμή, μπορείς να παραλείψεις και τα δύο:
vals := []int{10, 20, 30}
count := 0
for range vals {
count++
}
// count == 3