Menu

Golang While-Schleife: while und do-while in Go schreiben

Go hat kein while-Schlüsselwort. Eine for-Schleife mit nur einer Bedingung ist die while-Schleife von Go, for ohne Bedingung ist eine Endlosschleife, und ein do-while ist eine Endlosschleife mit der Prüfung am Ende.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

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.
  • while schreiben. while x < 5 {} liefert syntax error: unexpected name x at end of statement, weil while kein Schlüsselwort ist; der Compiler liest es als gewöhnlichen Namen.
  • Klammern aus Gewohnheit. for (x < 5) {} kompiliert, und gofmt entfernt 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. Deklarier n vor 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.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S