Schleifen

Go kennt nur einen einzigen Befehl für Schleifen: for. Dieser Befehl kommt in zwei unterschiedlichen Formen vor, einmal in der Form, wie sie aus Programmiersprachen wie C bekannt sind, und einmal als Iterator, wie sie auch in Programmiersprachen wie Ruby vorkommen (dort: each_with_index()).

Standardform

In der einfachsten Form ist die for-Schleife eine »Endlosschleife«, deren Inhalt immer wieder ausgeführt wird:

package main

import "fmt"

func main() {
    for {
        fmt.Println("Hallo schöne Welt")
    }
}

Wenn du das Programm laufen lässt, musst du es abbrechen, da die Schleife keine Abbruchbedingung hat. Obige Schleife ist dasselbe wie

for true {
    fmt.Println("Hallo schöne Welt")
}

was wiederum dasselbe ist wie for ; true ; { ... }. Die allgemeine Form der Schleife sieht so aus:

for ‹init› ; ‹bedingung› ; ‹post›  { ... }

Wobei ‹bedingung› ein boolescher Ausdruck ist (der also true oder false ergeben muss). ‹init› und ‹post› sind einfache Anweisungen. ‹init› wird einmal vor Schleifenbeginn ausgeführt, ‹post› nach jeder Iteration am Ende des Blocks. Was sich sehr theoretisch anhört hat die praktische Form wie:

package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(i, "Hallo schöne Welt")
    }
}

Versuche zu überlegen, was das Programm ausgibt, bevor du es ausprobierst!

Hier wird i := 0 einmal zu Beginn der Schleife ausgeführt, die Schleife solange durchlaufen wie die Bedingung i < 10 wahr ergibt und am Ende des Blocks wird mit i++ i um eins erhöht. Ein wichtiger Hinweis: Die in ‹init› definierten Variablen sind nur innerhalb der Schleife sichtbar.

for ... := range

Die zweite Form der for-Schleife iteriert über einen der Datentypen, die eine Menge an Elementen beinhalten kann (Array, Slice, String, Map und Channel). Diese Schleife hat folgenden Aufbau:

for k, v := range objekt {
    ...
}

Die Variablen k und v haben je nach Typ des Objekts eine unterschiedliche Bedeutung. Bei einem Feld (Slice oder Array) ist die erste Variable der Index, bei einer Map ist das der Schlüssel. v ist bei den drei Strukturen der Wert, der unter k angesprochen wird.

package main

import "fmt"

func main() {
    alter := map[string]int{
        "Andreas": 23,
        "Marie":   37,
        "Peter":   27,
        "Karina":  27,
    }
    for k, v := range alter {
        fmt.Println(k, "ist", v, "Jahre alt.")
    }
}

Hier wird die Map, die in der Variable alter gespeichert ist, ohne eine bestimmte Reihenfolge durchlaufen und nacheinander der Variablen k den Namen und v das Alter zugeordnet (und ausgegeben).

Ausbruch aus der Schleife (break)

Man kann aus einer Schleife ausbrechen. Der Befehl dazu heißt break und wird wie folgt benutzt:

package main

import "fmt"

func main() {
    zähler := 0
    for {
        if zähler == 4 {
            break
        }
        fmt.Println("Hallo schöne Welt")
        zähler++
    }
}

break unterbricht die innerste for Schleife (im Übrigen auch select und switch Anweisungen, dazu später mehr). Wenn man mehrere for-Schleifen geschachtelt hat, kann man sich mit Sprungmarken (Labels) helfen:

package main

import "fmt"

func main() {
Hauptschleife:
    for j := 0; j < 10; j++ {
        for k := 0; k < 10; k++ {
            fmt.Println(j, k, "Hallo schöne Welt")
            if k == 4 {
                break Hauptschleife
            }

        }
    }
}

Probiere das Programm einmal ohne die Sprungmarke Hauptschleife aus und einmal mit. Was passiert?

Hier sind zwei Schleifen ineinander geschachtelt. Das break in der innersten Schleife würde ohne Sprungmarke lediglich bewirken, dass die innere Schleife nach fünf Durchläufen abgebrochen wird, die äußere Schleife aber weiter zehn Mal durchläuft. Mit Sprungmarke wird auch die äußere Schleife nach der fünften Iteration abgebrochen und mit dem Programmcode fortgeführt, der nach der Schleife steht.