Einführung
Bei der Computerprogrammierung ist aloop eine Codestruktur, die sich wiederholt, um einen Code wiederholt auszuführen, häufig bis eine bestimmte Bedingung erfüllt ist. Durch die Verwendung von Schleifen in der Computerprogrammierung können Sie ähnliche Aufgaben mehrmals automatisieren und wiederholen. Stellen Sie sich vor, Sie hätten eine Liste der zu verarbeitenden Dateien oder möchten die Anzahl der Zeilen in einem Artikel zählen. Sie würden eine Schleife in Ihrem Code verwenden, um diese Art von Problemen zu lösen.
In Go implementiert einefor
-Schleife die wiederholte Ausführung von Code basierend auf einem Schleifenzähler oder einer Schleifenvariablen. Im Gegensatz zu anderen Programmiersprachen mit mehreren Schleifenkonstrukten wiewhile
,do
usw. verfügt Go nur über die Schleifefor
. Dies dient dazu, Ihren Code klarer und lesbarer zu machen, da Sie sich nicht um mehrere Strategien kümmern müssen, um dasselbe Schleifenkonstrukt zu erzielen. Durch diese verbesserte Lesbarkeit und die geringere kognitive Belastung während der Entwicklung ist Ihr Code auch weniger fehleranfällig als in anderen Sprachen.
In diesem Tutorial erfahren Sie, wie diefor
-Schleife von Go funktioniert, einschließlich der drei Hauptvarianten ihrer Verwendung. Zunächst zeigen wir, wie verschiedene Arten vonfor
-Schleifen erstellt werden, gefolgt von der Schleife durchsequential data types in Go. Wir werden zum Schluss erklären, wie man verschachtelte Schleifen verwendet.
ForClause- und Condition-Schleifen deklarieren
Um eine Vielzahl von Anwendungsfällen zu berücksichtigen, gibt es drei verschiedene Möglichkeiten,for
-Schleifen in Go mit jeweils eigenen Funktionen zu erstellen. Diese dienen zum Erstellen einerfor
-Schleife mit einemCondition, einemForClause oder einemRangeClause. In diesem Abschnitt wird erklärt, wie die ForClause- und Condition-Varianten deklariert und verwendet werden.
Schauen wir uns zunächst an, wie wir einefor
-Schleife mit der ForClause verwenden können.
EinForClause loop hat eininitial statement, gefolgt von einemcondition und einempost statement. Diese sind in der folgenden Syntax angeordnet:
for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
[Action]
}
Um zu erklären, was die vorhergehenden Komponenten tun, schauen wir uns einefor
-Schleife an, die mithilfe der ForClause-Syntax um einen bestimmten Wertebereich inkrementiert:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Lassen Sie uns diese Schleife auflösen und jedes Teil identifizieren.
Der erste Teil der Schleife isti := 0
. Dies ist die erste Aussage:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Es besagt, dass wir eine Variable namensi
deklarieren und den Anfangswert auf0
setzen.
Weiter ist die Bedingung:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
In diesem Zustand haben wir angegeben, dassi
zwar kleiner als der Wert von5
ist, die Schleife jedoch die Schleife fortsetzen sollte.
Schließlich haben wir die Post-Anweisung:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
In der post-Anweisung erhöhen wir die Schleifenvariablei
jedes Mal um eins, wenn eine Iteration mit dem Operatori++
increment auftritt.
Wenn wir dieses Programm ausführen, sieht die Ausgabe folgendermaßen aus:
Output0
1
2
3
4
Die Schleife lief 5 mal. Zunächst wurdei
auf0
gesetzt und dann überprüft, obi
kleiner als5
war. Da der Wert voni
kleiner als5
war, wurde die Schleife ausgeführt und die Aktion vonfmt.Println(i)
ausgeführt. Nach Beendigung der Schleife wurde die Post-Anweisung voni++
aufgerufen und der Wert voni
um 1 erhöht.
[.note] #Note: Beachten Sie, dass wir bei der Programmierung tendenziell bei Index 0 beginnen. Obwohl 5 Zahlen ausgedruckt werden, reichen sie von 0 bis 4
#
Wir sind nicht darauf beschränkt, bei 0 zu beginnen oder bei einem bestimmten Wert zu enden. Wir können unserer anfänglichen Anweisung einen beliebigen Wert zuweisen und auch bei einem beliebigen Wert in unserer post-Anweisung aufhören. Auf diese Weise können wir einen beliebigen Bereich zum Durchlaufen erstellen:
for i := 20; i < 25; i++ {
fmt.Println(i)
}
Hier reicht die Iteration von 20 (einschließlich) bis 25 (ausschließlich), sodass die Ausgabe folgendermaßen aussieht:
Output20
21
22
23
24
Wir können auch unsere post-Anweisung verwenden, um bei verschiedenen Werten zu inkrementieren. Dies ähneltstep
in anderen Sprachen:
Verwenden wir zunächst eine post-Anweisung mit einem positiven Wert:
for i := 0; i < 15; i += 3 {
fmt.Println(i)
}
In diesem Fall wird diefor
-Schleife so eingerichtet, dass die Zahlen von 0 bis 15 ausgedruckt werden, jedoch in Schritten von 3, so dass nur jede dritte Zahl wie folgt gedruckt wird:
Output0
3
6
9
12
Wir können auch einen negativen Wert für unser Argument nach der Anweisung verwenden, um rückwärts zu iterieren. Wir müssen jedoch unsere Argumente für die ursprüngliche Anweisung und die Bedingung entsprechend anpassen:
for i := 100; i > 0; i -= 10 {
fmt.Println(i)
}
Hier setzen wiri
auf einen Anfangswert von100
, verwenden die Bedingungi < 0
, um bei0
anzuhalten, und die Post-Anweisung verringert den Wert um 10 mit-=
Operator. Die Schleife beginnt bei100
und endet bei0
und nimmt mit jeder Iteration um 10 ab. Wir können dies in der Ausgabe sehen:
Output100
90
80
70
60
50
40
30
20
10
Sie können auch die anfängliche Anweisung und die post-Anweisung von der Syntax vonfor
ausschließen und nur die Bedingung verwenden. Dies ist alsCondition loop bekannt:
i := 0
for i < 5 {
fmt.Println(i)
i++
}
Dieses Mal haben wir die Variablei
getrennt von derfor
-Schleife in der vorhergehenden Codezeile deklariert. Die Schleife hat nur eine Bedingungsklausel, die prüft, obi
kleiner als5
ist. Solange die Bedingungtrue
ergibt, wird die Schleife weiter iteriert.
Manchmal wissen Sie möglicherweise nicht, wie viele Iterationen Sie benötigen, um eine bestimmte Aufgabe auszuführen. In diesem Fall können Sie alle Anweisungen weglassen und das Schlüsselwortbreak
verwenden, um die Ausführung zu beenden:
for {
if someCondition {
break
}
// do action here
}
Ein Beispiel hierfür könnte sein, wenn wir aus einer unbestimmt großen Struktur wiebuffer lesen und nicht wissen, wann wir mit dem Lesen fertig sind:
buffer.go
package main
import (
"bytes"
"fmt"
"io"
)
func main() {
buf := bytes.NewBufferString("one\ntwo\nthree\nfour\n")
for {
line, err := buf.ReadString('\n')
if err != nil {
if err == io.EOF {
fmt.Print(line)
break
}
fmt.Println(err)
break
}
fmt.Print(line)
}
}
Im vorhergehenden Code deklariertbuf :=bytes.NewBufferString("one
two
three
four
")
einen Puffer mit einigen Daten. Da wir nicht wissen, wann der Puffer das Lesen beendet, erstellen wir einefor
-Schleife ohne Klausel. Innerhalb derfor
-Schleife lesen wir mitline, err := buf.ReadString('
')
eine Zeile aus dem Puffer und prüfen, ob beim Lesen aus dem Puffer ein Fehler aufgetreten ist. Wenn ja, beheben wir den Fehler unduse the break
keyword to exit the for loop. Mit diesenbreak
Punkten müssen Sie keine Bedingung einschließen, um die Schleife zu stoppen.
In diesem Abschnitt haben wir gelernt, wie eine ForClause-Schleife deklariert und zum Durchlaufen eines bekannten Wertebereichs verwendet wird. Wir haben auch gelernt, wie man mit einer Bedingungsschleife iteriert, bis eine bestimmte Bedingung erfüllt ist. Als Nächstes erfahren Sie, wie die RangeClause zum Durchlaufen sequenzieller Datentypen verwendet wird.
Sequentielle Datentypen mit RangeClause durchlaufen
In Go werden häufigfor
-Schleifen verwendet, um die Elemente von sequentiellen oder Sammlungsdatentypen wieslices, arrays undstrings zu durchlaufen. Um dies zu vereinfachen, können wir einefor
-Schleife mitRangeClause-Syntax verwenden. Während Sie sequentielle Datentypen mithilfe der ForClause-Syntax durchlaufen können, ist RangeClause übersichtlicher und einfacher zu lesen.
Bevor wir uns mit der RangeClause befassen, wollen wir uns ansehen, wie wir mithilfe der ForClause-Syntax durch ein Segment iterieren können:
main.go
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i := 0; i < len(sharks); i++ {
fmt.Println(sharks[i])
}
}
Wenn Sie dies ausführen, erhalten Sie die folgende Ausgabe, bei der jedes Element des Slice ausgedruckt wird:
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
Verwenden Sie jetzt die RangeClause, um dieselben Aktionen auszuführen:
main.go
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i, shark := range sharks {
fmt.Println(i, shark)
}
}
In diesem Fall drucken wir jedes Element in der Liste aus. Obwohl wir die Variableni
undshark
verwendet haben, hätten wir die Variable auch alle anderenvalid variable name nennen können und würden die gleiche Ausgabe erhalten:
Output0 hammerhead
1 great white
2 dogfish
3 frilled
4 bullhead
5 requiem
Wenn Sierange
für ein Slice verwenden, werden immer zwei Werte zurückgegeben. Der erste Wert ist der Index, in dem sich die aktuelle Iteration der Schleife befindet, und der zweite Wert ist der Wert an diesem Index. In diesem Fall betrug der Index für die erste Iteration0
und der Werthammerhead
.
Manchmal wollen wir nur den Wert innerhalb der Slice-Elemente, nicht den Index. Wenn wir den vorhergehenden Code ändern, um nur den Wert auszudrucken, erhalten wir einen Fehler bei der Kompilierung:
main.go
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i, shark := range sharks {
fmt.Println(shark)
}
}
Outputsrc/range-error.go:8:6: i declared and not used
Dai
in derfor
-Schleife deklariert, aber nie verwendet wird, antwortet der Compiler mit dem Fehleri declared and not used
. Dies ist derselbe Fehler, den Sie in Go erhalten, wenn Sie eine Variable deklarieren und nicht verwenden.
Aus diesem Grund hat Goblank identifier, was ein Unterstrich (_
) ist. In einerfor
-Schleife können Sie den leeren Bezeichner verwenden, um alle vom Schlüsselwortrange
zurückgegebenen Werte zu ignorieren. In diesem Fall möchten wir den Index ignorieren, der das erste zurückgegebene Argument ist.
main.go
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for _, shark := range sharks {
fmt.Println(shark)
}
}
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
Diese Ausgabe zeigt, dass diefor
-Schleife durch das String-Slice iteriert und jedes Element aus dem Slice ohne Index gedruckt hat.
Sie können auchrange
verwenden, um Elemente zu einer Liste hinzuzufügen:
main.go
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for range sharks {
sharks = append(sharks, "shark")
}
fmt.Printf("%q\n", sharks)
}
Output['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark']
Hier haben wir für jedes Element der Länge dessharks
-Slice eine Platzhalterzeichenfolge von"shark"
hinzugefügt.
Beachten Sie, dass wir den leeren Bezeichner_
nicht verwenden mussten, um einen der Rückgabewerte des Operatorsrange
zu ignorieren. Mit Go können wir den gesamten Deklarationsteil derrange
-Anweisung weglassen, wenn wir keinen der Rückgabewerte verwenden müssen.
Wir können auch den Operatorrange
verwenden, um Werte eines Slice einzugeben:
main.go
package main
import "fmt"
func main() {
integers := make([]int, 10)
fmt.Println(integers)
for i := range integers {
integers[i] = i
}
fmt.Println(integers)
}
In diesem Beispiel wird das Sliceintegers
mit zehn leeren Werten initialisiert, aber diefor
-Schleife setzt alle Werte in der Liste wie folgt:
Output[0 0 0 0 0 0 0 0 0 0]
[0 1 2 3 4 5 6 7 8 9]
Wenn wir zum ersten Mal den Wert des Sliceintegers
drucken, sehen wir alle Nullen. Dann durchlaufen wir jeden Index und setzen den Wert auf den aktuellen Index. Wenn wir dann den Wert vonintegers
ein zweites Mal drucken, zeigt dies, dass alle jetzt einen Wert von0
bis9
haben.
Wir können auch den Operatorrange
verwenden, um jedes Zeichen in einer Zeichenfolge zu durchlaufen:
main.go
package main
import "fmt"
func main() {
sammy := "Sammy"
for _, letter := range sammy {
fmt.Printf("%c\n", letter)
}
}
OutputS
a
m
m
y
Beim Durchlaufen vonmap gibtrange
sowohlkey als auchvalue zurück:
main.go
package main
import "fmt"
func main() {
sammyShark := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
for key, value := range sammyShark {
fmt.Println(key + ": " + value)
}
}
Outputcolor: blue
location: ocean
name: Sammy
animal: shark
[.note] #Note: Es ist wichtig zu beachten, dass die Reihenfolge, in der eine Karte zurückgegeben wird, zufällig ist. Jedes Mal, wenn Sie dieses Programm ausführen, erhalten Sie möglicherweise ein anderes Ergebnis.
#
Nachdem wir nun gelernt haben, wie sequentielle Daten mitrange
for
-Schleifen durchlaufen werden, schauen wir uns an, wie Schleifen innerhalb von Schleifen verwendet werden.
Geschachtelt für Schleifen
Schleifen können in Go wie in anderen Programmiersprachen verschachtelt werden. Nesting ist, wenn wir ein Konstrukt in einem anderen haben. In diesem Fall ist eine verschachtelte Schleife eine Schleife, die in einer anderen Schleife auftritt. Diese können nützlich sein, wenn Sie eine Schleifenaktion für jedes Element eines Datensatzes ausführen möchten.
Verschachtelte Schleifen ähneln strukturellnested if
statements. Sie sind so aufgebaut:
for {
[Action]
for {
[Action]
}
}
Das Programm trifft zuerst auf die äußere Schleife und führt ihre erste Iteration aus. Diese erste Iteration löst die innere, verschachtelte Schleife aus, die dann vollständig ausgeführt wird. Dann kehrt das Programm an den Anfang der äußeren Schleife zurück, schließt die zweite Iteration ab und löst erneut die verschachtelte Schleife aus. Die verschachtelte Schleife wird wieder vollständig ausgeführt, und das Programm kehrt an den Anfang der äußeren Schleife zurück, bis die Sequenz abgeschlossen ist oder eine Unterbrechung oder eine andere Anweisung den Prozess unterbricht.
Implementieren wir eine verschachteltefor
-Schleife, damit wir genauer hinschauen können. In diesem Beispiel durchläuft die äußere Schleife eine Schicht von Ganzzahlen, die alsnumList
bezeichnet wird, und die innere Schleife durchläuft eine Schicht von Zeichenfolgen, die alsalphaList
bezeichnet wird.
main.go
package main
import "fmt"
func main() {
numList := []int{1, 2, 3}
alphaList := []string{"a", "b", "c"}
for _, i := range numList {
fmt.Println(i)
for _, letter := range alphaList {
fmt.Println(letter)
}
}
}
Wenn wir dieses Programm ausführen, erhalten wir die folgende Ausgabe:
Output1
a
b
c
2
a
b
c
3
a
b
c
Die Ausgabe zeigt, dass das Programm die erste Iteration der äußeren Schleife durch Drucken von1
abschließt, was dann die Fertigstellung der inneren Schleife auslöst und nacheinandera
,b
,c
druckt . Sobald die innere Schleife abgeschlossen ist, kehrt das Programm zum oberen Rand der äußeren Schleife zurück, druckt2
und druckt dann erneut die innere Schleife in ihrer Gesamtheit (a
,b
,c
) s) usw.
Verschachteltefor
-Schleifen können nützlich sein, um Elemente in Slices zu durchlaufen, die aus Slices bestehen. Wenn wir in einem aus Slices zusammengesetzten Slice nur einefor
-Schleife verwenden, gibt das Programm jede interne Liste als Element aus:
main.go
package main
import "fmt"
func main() {
ints := [][]int{
[]int{0, 1, 2},
[]int{-1, -2, -3},
[]int{9, 8, 7},
}
for _, i := range ints {
fmt.Println(i)
}
}
Output[0 1 2]
[-1 -2 -3]
[9 8 7]
Um auf jedes einzelne Element der internen Slices zuzugreifen, implementieren wir eine verschachteltefor
-Schleife:
main.go
package main
import "fmt"
func main() {
ints := [][]int{
[]int{0, 1, 2},
[]int{-1, -2, -3},
[]int{9, 8, 7},
}
for _, i := range ints {
for _, j := range i {
fmt.Println(j)
}
}
}
Output0
1
2
-1
-2
-3
9
8
7
Wenn wir hier eine verschachteltefor
-Schleife verwenden, können wir die einzelnen in den Slices enthaltenen Elemente durchlaufen.
Fazit
In diesem Tutorial haben wir gelernt, wie manfor
-Schleifen deklariert und verwendet, um sich wiederholende Aufgaben in Go zu lösen. Wir haben auch die drei verschiedenen Variationen einerfor
-Schleife und den Zeitpunkt ihrer Verwendung kennengelernt. Lesen SieUsing Break and Continue Statements When Working with Loops in Go, um mehr überfor
-Schleifen und deren Steuerung zu erfahren.