Go hat kein while-Schlüsselwort. Schreib for gefolgt von einer Bedingung, und du hast eine while-Schleife:
Die Bedingung wird vor jedem Durchlauf geprüft. Ist sie schon am Anfang falsch, läuft der Rumpf nie. Das entspricht while (balance < 2000) in C, Java oder JavaScript, nur ohne Klammern und ohne das Schlüsselwort. Die Designer von Go haben sich für ein einziges Schleifen-Schlüsselwort für alle Schleifenformen entschieden; alle vier Formen findest du auf der Seite zur for-Schleife.
while(true): die Endlosschleife
Lässt du die Bedingung ganz weg, läuft die Schleife, bis etwas im Rumpf sie beendet:
for { } ist die idiomatische Schreibweise. for true { } kompiliert auch, liest sich aber, als käme der Autor aus einer anderen Sprache.
Vier Dinge beenden eine Endlosschleife: break (verlässt die Schleife), return (verlässt die Funktion), eine Panic und os.Exit. Ein Programm, dessen main in for {} steckt und keins davon enthält, läuft, bis es beendet wird. Für einen Server oder Worker ist das genau richtig.
do-while
Ein do-while führt den Rumpf einmal aus, bevor die Bedingung geprüft wird. Go hat dafür keine eigene Syntax. Setz die Prüfung ans Ende einer Endlosschleife:
Der Rumpf läuft in jedem Fall mindestens einmal, und das ist die entscheidende Eigenschaft von do-while. Die Zufallsquelle nutzt einen festen Seed, damit die Ausgabe bei jedem Lauf gleich ist; für echten Zufall nimmst du rand.IntN ohne geseedete Quelle.
Eine zweite Form behält die Bedingung im Kopf und erzwingt den ersten Durchlauf:
for first := true; first || condition(); first = false {
// body
}
Das funktioniert, aber die Endlosschleife mit einem break am Ende liest sich leichter, und so macht es der meiste Go-Code.
Lesen, bis nichts mehr kommt
Die häufigste while-Schleife in echtem Go-Code liest Eingaben, bis sie aufgebraucht sind. bufio.Scanner ist genau dafür gebaut: Scan gibt am Ende der Eingabe oder bei einem Fehler false zurück und ist damit die Schleifenbedingung:
Ersetz strings.NewReader(input) durch os.Stdin, und dieselbe Schleife liest die Eingabe des Nutzers Zeile für Zeile. Prüf nach der Schleife scanner.Err(): Wenn Scan false liefert, weißt du noch nicht, ob die Eingabe normal endete oder ein Fehler auftrat.
break und continue
Beide funktionieren in jeder Form von for:
In einer Schleife mit nur einer Bedingung springt continue direkt zur Bedingung. Das macht einen subtilen Bug leicht: Wird der Zähler unten im Rumpf aktualisiert, überspringt ein continue darüber die Aktualisierung, und die Schleife endet nie. Aktualisier den Zähler oben, wie im Beispiel, oder nimm ein for mit drei Klauseln, dessen Post-Anweisung auch nach continue läuft.
Auf etwas warten
Eine Schleife, die auf eine Bedingung wartet, sollte blockieren oder schlafen, nicht leer kreisen:
// Wrong: burns a CPU core while waiting
for !ready {
}
// Better: poll with a delay
for !isReady() {
time.Sleep(100 * time.Millisecond)
}
Eine normale Variable abzufragen, die eine andere Goroutine schreibt, ist außerdem ein Data Race. Zwischen Goroutinen wartest du stattdessen auf einen Channel, eine sync.WaitGroup oder eine sync.Cond, oder du nutzt select mit einem Timer. Für Retry-Schleifen mit einem Limit ist ein zählendes for besser, damit die Schleife nicht ewig laufen kann:
for attempt := 1; attempt <= 5; attempt++ {
if err := connect(); err == nil {
break
}
time.Sleep(time.Duration(attempt) * 200 * time.Millisecond)
}
Häufige Fehler
- Die Bedingungsvariable nicht ändern.
for i < 10 { fmt.Println(i) }endet nie. Jede while-Schleife braucht etwas im Rumpf, das sie Richtung Ausgang bewegt. whileschreiben.while x < 5 {}liefertsyntax error: unexpected name x at end of statement, weilwhilekein Schlüsselwort ist; der Compiler liest es als gewöhnlichen Namen.- Klammern aus Gewohnheit.
for (x < 5) {}kompiliert, undgofmtentfernt die Klammern. - Die Variable in der Schleife deklarieren.
for n := 10; n > 0 {}ist ein Syntaxfehler; eine Schleife mit Init-Klausel braucht alle drei Klauseln. Deklariernvor der Schleife oder schreib die vollständige Form mit drei Klauseln.
Häufig gestellte Fragen
Hat Go eine while-Schleife?
Nicht als Schlüsselwort. Go verwendet for für jede Schleife, und ein for mit nur einer Bedingung ist genau eine while-Schleife:
for count < 10 {
count++
}
Die Bedingung wird vor jedem Durchlauf geprüft, genau wie bei while (count < 10) in C oder Java.
Wie schreibe ich while(true) in Go?
Schreib for ohne etwas dahinter: for { ... }. Die Schleife läuft, bis ein break, return, eine Panic oder os.Exit sie beendet. for true { ... } kompiliert auch, aber for { } ist die idiomatische Form.
Wie schreibe ich eine do-while-Schleife in Go?
Nimm eine Endlosschleife und setz die Prüfung der Bedingung ans Ende des Rumpfs:
for {
// body runs at least once
if !condition {
break
}
}
Der Rumpf läuft immer einmal, bevor die Bedingung geprüft wird. Genau das bedeutet do-while.