0Pricing
Go Academy · Lektion

Goroutines starten

Das Schlüsselwort go, der Lebenszyklus von Goroutines und WaitGroups

Goroutines starten ist eine kostenlose Go Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Go Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Go Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist eine Goroutine?

Eine Goroutine ist eine leichtgewichtige, nebenläufig ausgeführte Funktion, die von der Go-Laufzeitumgebung verwaltet wird. Goroutines sind wesentlich kostengünstiger als Betriebssystem-Threads — Sie können Tausende davon ausführen:

  • Start mit dem Schlüsselwort go
  • Anfangs-Stack ~2 KB (wächst dynamisch)
  • Von der Go-Laufzeitumgebung eingeplant, nicht vom Betriebssystem
  • Kommunikation über Channels statt über gemeinsam genutzten Speicher

Das Schlüsselwort go

Stellen Sie jedem Funktionsaufruf go voran, um ihn als Goroutine zu starten:

package main
import ("fmt"; "time")

func greet(name string) {
    fmt.Printf("Hello, %s!\n", name)
}

func main() {
    go greet("Alice")   // runs concurrently
    go greet("Bob")     // runs concurrently
    time.Sleep(100 * time.Millisecond) // wait for goroutines
    fmt.Println("done")
}

Lebenszyklus einer Goroutine

Eine Goroutine startet, sobald die Anweisung go ausgeführt wird, und endet, wenn ihre Funktion zurückkehrt. Wenn main zurückkehrt, werden alle Goroutines beendet:

package main
import ("fmt"; "time")

func worker(id int) {
    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Duration(id) * 50 * time.Millisecond)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    for i := 1; i <= 3; i++ {
        go worker(i)
    }
    time.Sleep(300 * time.Millisecond) // naive wait
}

sync.WaitGroup zur Koordination

Verwenden Sie sync.WaitGroup anstelle von sleep, um auf das Ende von Goroutines zu warten:

package main
import ("fmt"; "sync")

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()  // signal completion
    fmt.Printf("Worker %d working\n", id)
}

func main() {
    var wg sync.WaitGroup
    for i := 1; i <= 5; i++ {
        wg.Add(1)           // register one goroutine
        go worker(i, &wg)
    }
    wg.Wait()               // block until all Done()
    fmt.Println("all workers finished")
}

Anonyme Goroutines

Starten Sie eine anonyme Funktion direkt als Goroutine — nützlich für nebenläufige Aufgaben direkt an der Aufrufstelle:

package main
import ("fmt"; "sync")

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        i := i  // capture loop variable
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Printf("goroutine %d\n", i)
        }()
    }
    wg.Wait()
}

Tücken beim Erfassen von Schleifenvariablen

Wenn Sie die Schleifenvariable nicht erfassen, sehen möglicherweise alle Goroutines denselben (letzten) Wert — ein klassischer Go-Nebenläufigkeitsfehler:

package main
import ("fmt"; "sync")

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func(n int) {  // pass i as argument — safe
            defer wg.Done()
            fmt.Println(n)  // prints 0, 1, 2 in some order
        }(i)
    }
    wg.Wait()
}

Goroutines vs. Threads

Warum Goroutines gegenüber Betriebssystem-Threads bevorzugt werden:

  • 2 KB Anfangs-Stack gegenüber ~1 MB bei Betriebssystem-Threads
  • Erstellung dauert Mikrosekunden statt Millisekunden
  • Die Go-Laufzeitumgebung verteilt Goroutines auf GOMAXPROCS Betriebssystem-Threads
  • Der Wechsel zwischen Goroutines erfolgt kooperativ — ohne Beteiligung des Kernels
  • Go übernimmt die Planung, Sie konzentrieren sich auf die Logik

GOMAXPROCS

runtime.GOMAXPROCS steuert, wie viele Betriebssystem-Threads Goroutines parallel ausführen (standardmäßig entspricht der Wert der Anzahl der CPUs):

package main
import ("fmt"; "runtime")

func main() {
    // Default: number of available CPU cores
    fmt.Println("CPUs:", runtime.NumCPU())
    fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 0 = query without changing

    // Set to 1 for debugging race conditions:
    // runtime.GOMAXPROCS(1)

    fmt.Println("Goroutines:", runtime.NumGoroutine())
}

Goroutine-Leaks

Ein Goroutine-Leak tritt auf, wenn eine Goroutine gestartet wird, aber nie endet. Häufige Ursachen sind ein blockierter Channel-Empfang, ein blockierter Mutex oder fehlende Abbruchmöglichkeiten:

package main
import ("fmt"; "time"; "runtime")

func leaky() {
    ch := make(chan int)  // nobody sends to ch
    go func() {
        v := <-ch  // blocks forever — goroutine leaked!
        fmt.Println(v)
    }()
}

func main() {
    leaky()
    time.Sleep(10 * time.Millisecond)
    fmt.Println("goroutines:", runtime.NumGoroutine()) // > 1
}

Bewährte Vorgehensweisen für Goroutines

Richtlinien für Goroutines:

  • Stellen Sie immer sicher, wie eine Goroutine beendet wird
  • Verwenden Sie zur Synchronisierung eine WaitGroup oder Channels, nicht sleep
  • Übergeben Sie Schleifenvariablen als Funktionsargumente statt über eine Closure
  • Brechen Sie Goroutines mit einem Context ab, anstatt sie weiterlaufen zu lassen
  • Verwenden Sie den Race Detector: go run -race main.go

Kurztest

Wie vermeiden Sie den Fehler durch das Erfassen der Schleifenvariable in Goroutines korrekt?

Zusammenfassung: Goroutines starten

Zusammenfassung:

  • Start mit go fn() — leichtgewichtig und kostengünstig
  • Verwenden Sie sync.WaitGroup zum Warten: Add(1), defer Done(), Wait()
  • Erfassen Sie Schleifenvariablen als Argument oder durch erneute Deklaration
  • Stellen Sie immer sicher, wie jede Goroutine endet — so verhindern Sie Leaks
  • Verwenden Sie das -race-Flag, um Datenrennen zu erkennen

Häufig gestellte Fragen

Ist die Lektion „Goroutines starten“ kostenlos?

Ja — der vollständige Text von „Goroutines starten“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Go Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Go Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Goroutines starten“?

Das Schlüsselwort go, der Lebenszyklus von Goroutines und WaitGroups Du übst Go Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Go Academy zu starten?

Keine Vorkenntnisse erforderlich. Go Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Goroutines starten“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Go Academy-Lektion Code schreiben und ausführen?

Ja. Jede Go Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Goroutines starten
  2. Ungepufferte Channels
  3. Gepufferte Channels
  4. Channel-Richtung und Pipeline-Patterns
← Zurück zu Go Academy