Einführung
In der Programmierung ist ein Loop eine Code-Struktur, die ein Stück Code mehrfach ausführen lässt, oft bis zu einem bestimmten Condition erfolgt ist. Die Verwendung von Loops in der Computersprache erlaubt Ihnen, ähnliche Aufgaben automatisch und wiederholt zu schreiben. Denken Sie an eine Liste von Dateien, die Sie bearbeiten müssen, oder an die Zählung der Zeilen in einem Artikel. Sie würden einen Loop in Ihrem Code verwenden, um diese Typen von Problemen zu lösen.
Im Go-Programmieren implementiert der for
-Loop den Wiederholungsbetrieb des Codes auf Basis einer Schleife-Zähler oder -Variable. Unterschiedlich als andere Programmiersprachen, die mehrere Loop-Konstrukte wie z. B. while
, do
, usw. haben, hat Go nur den for
-Loop. Dies macht deine Code schneller lesbar und lesbarer als in anderen Sprachen, da du nicht mit mehreren Strategien zur Erreichen des gleichen Loop-Konstrukts beschäftigt sein musst. Dieser verbesserte Lesbarkeit und reduzierte kognitive Lasten während der Entwicklung werden auch deinen Code weniger fehlerhaft als in anderen Sprachen machen.
In diesem Tutorial lernen Sie, wie Go’s for
-Loop funktioniert, einschließlich der drei grundleglichen Varianten seiner Nutzung. Wir beginnen damit, indem wir zeigen, wie verschiedene Typen von for
-Schleifen zu erstellen, gehen danach aber daran, durch sequentielle Datentypen in Go zu iterieren. Wir schließen mit der Erklärung, wie man nested loops verwenden kann.
Die Anweisung für die Klausel „for“ und die Schleife mit Bedingungen
Um eine Vielzahl von Fallstudien zu berücksichtigen, gibt es drei unterschiedliche Wege, einen for
-Loop in Go zu definieren, jeder mit eigenen Fähigkeiten. Diese sind die Erstellung eines for
-Loops mit einer Bedingung, einem ForKlausel, oder einem RangeKlausel. In diesem Abschnitt erklären wir, wie Sie den ForKlausel und die Bedingungsvarianten verwenden können.
Zunächst schauen wir uns an, wie wir einen ForKlause-Loop erstellen können.
Ein ForKlausel-Schleife ist definiert als eine Anfangsstatement, gefolgt von einer Bedingung, und dann einem Nachstatement. Diese werden im folgenden Syntax arrangiert:
for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
[Action]
}
Um zu erklären was die vorherige Komponenten machen, lassen sich wir ein Beispiel mit dem ForKlause-Syntax ansehen, bei dem wir durch eine bestimmte Zahl von Werten inkrementieren:
Lasst uns diesen Loop niederschreiben und analysieren, was jede Teilstelle bedeutet.
Der erste Teil des Loops ist i := 0
. Dies ist das Anfangsstatement:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Es sagt, dass wir eine Variable namens i
definieren und ihren initialen Wert auf 0
setzen.
Danach ist die Bedingung:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
In dieser Bedingung stellten wir fest, dass der Loop solange fortfahren sollte, bis i
kleiner als die Wert 5
ist.
Schließlich haben wir den Nachstatement:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
In der Postanweisung erhöhen wir die Schleifenvariable i
um eins, wenn eine Iteration stattfindet, indem wir den i++
Inkrement-Operator verwenden.
Wenn wir dieses Programm ausführen, sieht die Ausgabe so aus:
Output0
1
2
3
4
Die Schleife lief 5 Mal. Anfangs wurde i
auf 0
gesetzt und dann getestet, ob i
kleiner als 5
war. Da der Wert von i
kleiner als 5
war, wurde die Schleife ausgeführt und die Aktion von fmt.Println(i)
wurde durchgeführt. Nachdem die Schleife beendet wurde, wurde die Postanweisung von i++
aufgerufen und der Wert von i
um eins erhöht.
Hinweis: Denken Sie daran, dass wir in der Programmierung oft mit dem Index 0 beginnen, weshalb obwohl 5 Zahlen ausgegeben werden, sie sich zwischen 0 und 4 bewegen.
Wir sind nicht anfängen bei 0 oder beenden bei einer bestimmten Wert eingeschränkt. Wir können jeder beliebigen Wert für unsere initiale Anweisung zuweisen und auch bei jedem Wert in unserer Postanweisung beenden. Dies ermöglicht es uns, jeglichen gewünschten Bereich zu iterieren:
Hier iteriert es von 20 (inklusive) bis 25 (exklusive), so sieht die Ausgabe so aus:
Output20
21
22
23
24
Wir können auch unsere Postanweisung mit anderen Werten inkrementieren. Dies ist ähnlich wie Schritt
in anderen Sprachen:
Zuerst verwenden wir eine Postanweisung mit einem positiven Wert:
for i := 0; i < 15; i += 3 {
fmt.Println(i)
}
In diesem Fall ist die for
-Schleife so eingestellt, dass die Zahlen von 0 bis 15 ausgegeben werden, aber mit einem Schritt von 3, sodass nur jeder dritte Zahl ausgegeben wird, wie folgt:
Output0
3
6
9
12
Wir können auch einen negativen Wert für den Argument des Post-Statements verwenden, um rückwärts zu iterieren, aber wir müssen unsere initiale Statement und die Bedingung argumente entsprechend anpassen:
Hier setzen wir i
mit einem initialen Wert von 100
, benutzen die Bedingung i < 0
um bei 0
zu stoppen und die Nachstatement mit dem Operator -=
um den Wert um 10 zu reduzieren. Die Schleife beginnt bei 100
und endet bei 0
, indem sie jede Iteration um 10 abnimmt. Dies können Sie im Ausgabenachstellen sehen:
Output100
90
80
70
60
50
40
30
20
10
Sie können auch das initiale Statement und das Nachstatement aus der for
Syntax herausnehmen und nur die Bedingung verwenden. Das ist was man als Konditionelle Schleife bezeichnet:
i := 0
for i < 5 {
fmt.Println(i)
i++
}
In diesem Fall haben wir die Variable i
separat vom for
Loop in der vorherigen Zeile definiert. Die Schleife hat nur eine Bedingungsclause, die überprüft, ob i
kleiner als 5
ist. Solange die Bedingung evaluiert wird als true
, wird die Schleife fortgesetzt.
Es gibt Situationen, in denen Sie nicht wissen, wie viele Iterationen Sie für ein bestimmtes Task benötigen werden. In diesem Fall können Sie alle Statements omittern und den break
-Keyword verwenden, um die Ausführung zu unterbrechen:
for {
if someCondition {
break
}
// do action here
}
Eine Beispiel dafür könnte sein, wenn Sie von einem unbestimmt großen Struktur wie einem Buffer lesen und Sie nicht wissen, bis wann sie fertig sind:
In dem vorherigen Code ist buf :=bytes.NewBufferString("one\ntwo\nthree\nfour\n")
ein Puffer mit Daten deklariert. Da wir nicht wissen, wann der Puffer beendet lesen wird, erstellen wir ein for
Loop ohne Klausel. Innerhalb des for
Loops verwenden wir line, err := buf.ReadString('\n')
, um eine Zeile vom Puffer zu lesen und zu prüfen, ob beim Lesen aus dem Puffer ein Fehler aufgetreten ist. Wenn ja, behandeln wir den Fehler und nutzen den Schlüsselwort break
, um das for Loop zu verlassen. Mit diesen break
Punkten müssen Sie keine Bedingung für das Beenden des Loops einbinden.
In diesem Abschnitt haben wir gelernt, wie ein ForClause Loop deklariert wird und wie er verwendet wird, um durch einen bekannten Wertbereich zu iterieren. Wir haben auch gelernt, wie ein Bedingung Loop verwendet wird, um bis zu einer bestimmten Bedingung zu iterieren. Nächstes Mal werden wir lernen, wie der RangeClause verwendet wird, um durch sequenzielle Datentypen zu iterieren.
Iterieren von sequenziellen Datentypen mit RangeClause
Es ist in Go häufig üblich, for
Schleifen zu verwenden, um über die Elemente von sequentiellen oder kollektiven Datentypen wie Slices, Arrays und Strings zu iterieren. Um dies erleichtert zu bekommen, kann man eine for
Schleife mit RangeClause Syntax verwenden. Obwohl man mittels der ForClause Syntax durch sequenteielle Datentypen iterieren kann, ist die RangeClause klarer und einfacher lesbar.
Bevor wir die RangeClause verwenden, lassen Sie uns anschauen, wie man über ein Slice iterieren kann, indem die ForClause Syntax verwendet wird:
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 man dies ausführt, erhält man die folgende Ausgabe, indem jedes Element des Slices ausgegeben wird:
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
Nun wird die gleiche Sequenz von Aktionen mit der RangeClause durchgeführt:
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 werden jedes Element der Liste ausgegeben. Obwohl wir die Variablen i
und shark
verwendet haben, hätte man die Variable auch mit jeder anderen gültigen Variablennamen bezeichnet und erhielte die gleiche Ausgabe:
Output0 hammerhead
1 great white
2 dogfish
3 frilled
4 bullhead
5 requiem
Wenn man mit range
auf ein Slice iteriert, gibt es immer zwei Werte zurück. Der erste Wert ist der Index, an dem die aktuelle Schleifeniteration befindet, und der zweite Wert ist der Wert an diesem Index. In diesem Fall war der Index für die erste Iteration 0
und der Wert war hammerhead
.
Manchmal möchten wir nur den Wert innerhalb der Slicen ausgeben, nicht die Indexnummern. Wenn wir das vorherige Code-Fragment so ändern, dass wir nur den Wert ausgeben, aber keine Indexnummern, dann erhalten wir einen Compile-Time-Fehler:
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
Da i im Loop deklariert wurde, aber nie verwendet wurde, antwortet der Compiler mit dem Fehler i declared and not used
. Das ist gleichfalls ein Fehler, den Sie in Go erhalten werden, wenn Sie eine Variable definieren und sie nicht verwenden.
Aufgrund diesem Grund hat Go die leere Identifikator, der Untersuchungszeichen (_
), um in einem Loop zu ignorieren, was vom range
-Keyword zurückgeliefert wird. Im Fall unseres Beispiels sollten wir die zweite Argument des range
-Operators ignorieren. In diesem Fall möchten wir die Indizes ignorieren, die als Erstargument vom range
-Operator zurückgeliefert werden.
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
Dieser Ausgabestream zeigt, dass der Loop durch die Zeichenfolge von Strings iteriert hat und jeder Eintrag der Slice ohne die Indexnummer ausgibt.
Sie können auch range
verwenden, um Elemente einer Liste hinzuzufügen:
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 jedes Element der Länge der sharks
-Slice mit einem Platzhalterstring von "shark"
hinzugefügt.
Beachten Sie, dass wir bei der range
-Anweisung keinen Teil der Deklaration auslassen durfen, wenn wir keine der beiden Rückgabewerte des range
-Operators benötigen. Go erlaubt uns auch, die gesamte Deklarationspart des range
-Statements auszulassen, falls wir keines der beiden Rückgabevaleuen benötigen.
Wir können auch range
verwenden, um Werte einer Slice zu füllen:
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 die Slice integers
mit zehn leeren Werten initialisiert, aber der for
-Loop setzt alle Werte in der Liste wie folgt fest:
Output[0 0 0 0 0 0 0 0 0 0]
[0 1 2 3 4 5 6 7 8 9]
Die erste Mal wenn wir den Wert der Slice integers
ausgeben sehen, sieht man alle Zerosen. Dann iterieren wir durch jede Index und setzen den Wert auf die aktuelle Indexzahl. Dann wenn wir den Wert von integers
ein zweites Mal ausgeben, zeigt dass sie jetzt alle Werte von 0
bis 9
haben.
Wir können auch die range
-Operator verwenden, um jedes Zeichen in einem String zu iterieren:
OutputS
a
m
m
y
Wenn wir über einen Map iterieren, range
wird beide das Key und das Value zurückgeben:
Outputcolor: blue
location: ocean
name: Sammy
animal: shark
Hinweis: Es ist wichtig zu beachten, dass die Reihenfolge, in der eine Map zurückgibt, zufällig ist. Bei jeder Ausführung des Programms könnten Sie ein anderes Ergebnis erhalten.
Nun haben wir gelernt, wie wir mit range
for
-Loop über sequentielle Daten iterieren. Jetzt schauen wir uns an, wie wir Loop-in-Loop verwenden können.
Nested For Loops
Schleifen können in Go wie in anderen Programmiersprachen verschachtelt werden. Verschachtelung bezeichnet das Vorhandensein eines Konstrukts innerhalb eines anderen. In diesem Fall handelt es sich um eine verschachtelte Schleife, die innerhalb einer anderen Schleife steht. Diese können nützlich sein, wenn Sie eine wiederholte Aktion für jedes Element eines Datensatzes ausführen möchten.
Verschachtelte Schleifen sind strukturell ähnlich zu verschachtelten if
-Anweisungen. Sie werden so erstellt:
for {
[Action]
for {
[Action]
}
}
Das Programm beginnt mit der äußeren Schleife, führt ihre erste Iteration aus. Diese erste Iteration triggert die integrierte, verschachtelte Schleife, die dann bis zum Ende Lauf ausführt. Danach geht das Programm an die Oberfläche der äußeren Schleife zurück, führt die zweite Iteration aus und löst erneut die verschachtelte Schleife aus. Diese läuft erneut bis zum Ende und das Programm geht erneut an die Oberfläche der äußeren Schleife zurück, bis die Sequenz abgeschlossen ist oder ein break-Aussage oder eine andere Anweisung den Prozess stört.
Lassen Sie uns ein Beispiel für eine verschachtelte for
-Schleife implementieren, um genauer zu sehen. In diesem Beispiel iteriert die äußere Schleife durch eine Integer-Slice namens numList
und die innere Schleife durch eine String-Slice namens alphaList
.
Wenn wir dieses Programm ausführen, erhalten wir die folgende Ausgabe:
Output1
a
b
c
2
a
b
c
3
a
b
c
Die Abbildung zeigt, dass das Programm die erste Iteration des äußeren Loops durch Ausgabe von 1
abgeschlossen hat, was dann den inneren Loop auslöst und sequenzielle Ausgaben von a
, b
, c
ermöglicht. Nachdem der innere Loop abgeschlossen ist, geht das Programm zurück zum Anfang des äußeren Loops, prüft 2
, dann wiederholt sich der innere Loop komplett (a
, b
, c
usw.), usw.
Nestierte for
-Schleifen können hilfreich sein, um über Elemente einer Slice zu iterieren, die wiederum Slice sind. Um jedes Einzelobjekt der internen Slicen zu bearbeiten, implementieren wir eine verschachtelte for
-Schleife:
Output[0 1 2]
[-1 -2 -3]
[9 8 7]
So können wir jeder einzelnen Item der internen Slicen zugreifen.
Output0
1
2
-1
-2
-3
9
8
7
Wenn wir hier eine verschachtelte for
-Schleife verwenden, können wir auf die einzelnen Elemente der Slice zugreifen.
Zusammenfassung
In diesem Tutorial haben wir gelernt, wie man for
-Schleifen in Go definiert und wie sie für die Losung von repetitiven Aufgaben eingesetzt werden. Wir haben auch die drei unterschiedlichen Variationen eines for
-Loops kennengelernt und wann sie benutzt werden sollen. Um mehr über for
-Schleifen zu lernen und die Kontrolle über deren Ablauf zu erhalten, lesen Sie Using Break and Continue Statements When Working with Loops in Go.
Source:
https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-go