🚀 Lehrpfad 3: Concurrency & Flow Control

Go 11: select Multiplexing, Timeouts & Context

Lerne die Kontrollzentrale fĂŒr Go-Channels: Multiplexe parallele Datenströme mit select, verhindere Deadlocks mit default und steuere SLAs & Stornierungen mit context.Context.

📂 Dateien dieser Lerneinheit:
📄 aufgabe.go (Startercode) đŸ§Ș test_aufgabe.go (Tests) 💡 musterloesung.go (Lösung) 📖 README.md

⚡ 1. Channel-Multiplexing mit select

Das select-Statement Ă€hnelt einem switch, jedoch fĂŒr Channel-Operationen: Es wartet darauf, dass mindestens ein Case kommunikationsbereit ist (Senden oder Empfangen). Sind mehrere Cases gleichzeitig bereit, wĂ€hlt Go pseudo-zufĂ€llig einen aus (Fairness-Garantie).

              â”Œâ”€â”€â”€ [Kanal A: Schnelle DB]   â”€â”€â”€â”
[select] ─────┌─── [Kanal B: Backup DB]     â”€â”€â”€â”Œâ”€â”€â”€> Wer zuerst Daten hat, gewinnt!
              â””─── [time.After(100ms): Timeout] ┘
select {
case msg1 := <-ch1:
    fmt.Println("Empfangen von ch1:", msg1)
case msg2 := <-ch2:
    fmt.Println("Empfangen von ch2:", msg2)
case <-time.After(500 * time.Millisecond):
    fmt.Println("⚠ Timeout! Beide KanĂ€le antworten zu langsam.")
default:
    // Wird SOFORT ausgefĂŒhrt, wenn kein Kanal bereit ist (Nicht-blockierend!)
    fmt.Println("Keine Daten vorhanden.")
}

đŸ›Ąïž 2. Robuste Cancellation mit context.Context

In Cloud-Microservices muss jeder Request bei Client-AbbrĂŒchen oder Timeouts sofort kaskadierend gestoppt werden. Das context-Paket ist in Go der offizielle Standard fĂŒr Deadlines und Abbruchsignale:

import (
    "context"
    "time"
)

func QueryDatabase(ctx context.Context) (string, error) {
    // Erstelle einen Channel fĂŒr das Abfrageergebnis
    resultCh := make(chan string, 1)

    go func() {
        // Simuliere langwierige DB-Abfrage
        time.Sleep(200 * time.Millisecond)
        resultCh <- "Kundendaten #42"
    }()

    select {
    case <-ctx.Done():
        // Wurde abgebrochen (Timeout oder Cancel)
        return "", ctx.Err() // z.B. context.DeadlineExceeded
    case res := <-resultCh:
        return res, nil
    }
}

func main() {
    // 🎯 Timeout von 100ms definieren:
    ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
    defer cancel() // Ressourcen immer freigeben!

    res, err := QueryDatabase(ctx)
    if err != nil {
        fmt.Println("Fehler:", err) // Ausgabe: context deadline exceeded
    }
}
🏱 Didaktische Analogie: Die Rezeption mit KĂŒchen-Gong

Stell dir einen Hotel-Concierge vor: Er hat ein rotes Telefon (ch1) fĂŒr den Zimmerservice und ein blaues Telefon (ch2) fĂŒr Taxibestellungen. Mit select nimmt er sofort den Hörer ab, der zuerst klingelt. Hat er eine Sanduhr aufgestellt (time.After) und nach 5 Minuten klingelt keines der Telefone, schließt er den Schalter (Timeout). context.Context ist der GeneralschlĂŒssel, mit dem die GeschĂ€ftsleitung alle laufenden AuftrĂ€ge auf einen Schlag abbricht.

📑 3. Cheat-Sheet: select & Context Patterns

Muster Code-Beispiel Zweck
Non-Blocking Read select { case v := <-ch: ... default: ... } Liest sofort ohne Blockieren des aktuellen Threads
Non-Blocking Write select { case ch <- v: ... default: ... } Verwirft oder puffert Daten wenn Channel voll ist
Hard Timeout case <-time.After(2 * time.Second): Bricht Warten nach Zeitintervall zuverlÀssig ab
Context Done case <-ctx.Done(): return ctx.Err() Kaskadierende Stornierung durch Microservice-Chain

🧠 Diagnostischer Selbst-Check

ÜberprĂŒfe dein VerstĂ€ndnis der Kernkonzepte und typischen Go-Fallen, bevor du die Übung in der Web-IDE bearbeitest.

🎯 Aufgaben & Checkliste in aufgabe.go

💡 Cloud-Architekt Best Practice: Context immer als erster Parameter

In Go ist es die feste Konvention, ctx context.Context immer als ersten Parameter an I/O- oder Netzwerkfunktionen zu ĂŒbergeben (z.B. func FetchUser(ctx context.Context, id int)).

đŸ’» In Web-IDE öffnen → ← ZurĂŒck zu Go 10 Weiter zu Go 12: Mutex & Thread Safety →