In Go wiederholt for range einen Block Code für die Werte eines Range-Ausdrucks.
Der Range-Ausdruck bestimmt, ob jede Iteration einen oder zwei Werte liefert.
range über ein Slice liefert der Reihe nach den Index und den Wert jedes Elements:
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30
range über eine Map liefert jeden Schlüssel und Wert, aber die Reihenfolge der Iteration ist nicht garantiert.
Go randomisiert die Iterationsreihenfolge von Maps bewusst, daher kann dasselbe Programm bei jedem Lauf eine andere Ausgabe erzeugen.
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 über einen String liefert den Byte-Index und jede Rune (Unicode-Codepunkt).
Im folgenden Beispiel belegt 子 drei Bytes, daher beginnt 猫 beim Byte-Index 3 und nicht bei 1.
for i, r := range "子猫" {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 3 29483 猫
Wenn du stattdessen Rune-Indizes brauchst, wandle den String in ein Slice von Runes um:
for i, r := range []rune("子猫") {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 1 29483 猫
range kann direkt über eine Ganzzahl iterieren und liefert Werte von 0 bis zu dieser Ganzzahl, diese aber nicht eingeschlossen.
Null und negative Werte sind gültig, erzeugen aber keine Iterationen.
for n := range 3 {
fmt.Println(n)
}
// 0
// 1
// 2
range akzeptiert einen Iterator vom Typ iter.Seq[V] oder iter.Seq2[K, V].
Ein Iterator ist eine Funktion, die eine Folge von Werten erzeugt, einen nach dem anderen.
Danach kann range diese Werte durchlaufen.
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
Schließlich kann range Werte empfangen, die über einen Channel gesendet werden, bis dieser Channel an anderer Stelle geschlossen wird.
Channels werden später im Syllabus des Tracks ausführlicher behandelt.
Go kompiliert nicht, wenn eine Variable deklariert, aber nie verwendet wird.
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(v)
}
// Go build failed: declared and not used: i
Wenn du nur den Wert brauchst, weise den Index oder Schlüssel _ zu, um ihn zu ignorieren.
vals := []int{10, 20, 30}
for _, v := range vals {
fmt.Println(v)
}
// 10
// 20
// 30
Wenn du nur den Index brauchst, lass ihn ganz weg:
vals := []int{10, 20, 30}
for i := range vals {
fmt.Println(i)
}
// 0
// 1
// 2
Wenn du weder den Index noch den Wert brauchst, kannst du beide weglassen:
vals := []int{10, 20, 30}
count := 0
for range vals {
count++
}
// count == 3