Direkt zum Hauptinhalt springen
eLearner.app
Modul 7 · Lektion 2 von 532/50 im Kurs~15 min
Lektionen des Moduls (2/5)

Kanäle: typisierte Kommunikation

Kanäle sind der idiomatische Mechanismus für die Kommunikation zwischen Goroutinen. Die Go-Philosophie (Rob Pike):

„Kommunizieren Sie nicht, indem Sie Erinnerungen teilen; teilen Sie Erinnerungen, indem Sie kommunizieren.“

Ein Kanal ist eine typisierte FIFO-Warteschlange, typsicher und gleichzeitig sicher verwenden. In Kombination mit go ist es der Hauptbaustein von Go Parallelität.

Erstellen, senden, empfangen

Go
ch := make(chan int)     // canale di int, unbuffered

go func() {
    ch <- 42             // invia (può bloccare)
}()

v := <-ch                // ricevi (può bloccare)
fmt.Println(v)           // 42

Syntax:

  • make(chan T) oder make(chan T, N) für gepuffert.
  • ch <- v sendet.
  • v := <-ch empfängt.
  • v, ok := <-ch empfängt mit einem Flag (ok = false, wenn der Kanal geschlossen UND leer ist).

Ungepuffert: Rendezvous

Ein ungepufferter Kanal (Kapazität 0) blockiert:

  • der Sender, bis ein Empfänger bereit ist;
  • der Empfänger, bis ein Absender bereit ist.

Es handelt sich um einen synchronen Termin: nützlich als „Signal“ oder als Garantie dass der Wert geliefert wurde.

Gepuffert: Warteschlange bis N

Go
ch := make(chan int, 3)
ch <- 1   // non blocca
ch <- 2   // non blocca
ch <- 3   // non blocca
ch <- 4   // BLOCCA: il buffer è pieno

Der Absender blockiert nur, wenn der Puffer voll ist; nur der Empfänger wenn es leer ist.

nah und aus der Distanz

Der Absender schließt den Kanal, wenn keine Werte mehr vorhanden sind:

Go
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)

for v := range ch {      // termina quando ch è chiuso E vuoto
    fmt.Println(v)
}

for range iteriert über einen Kanal, bis der Kanal geschlossen (und geleert) wird. Es ist das sauberste Muster für „Alles verbrauchen, was ankommt“.

Direktionalität in Signaturen

Funktionsparameter können die Richtung einschränken:

Go
func producer(out chan<- int) {   // solo invio
    out <- 1
    close(out)
}

func consumer(in <-chan int) {    // solo ricezione
    for v := range in {
        fmt.Println(v)
    }
}

chan<- T = Nur Senden, <-chan T = Nur Empfangen. Eine bidirektionale Kanal chan T kann an beide übergeben werden (implizite Konvertierung). Es verbessert die Übersichtlichkeit und beugt Fehlern vor.

Häufige Muster (Vorschau)

  • Worker-Pool: N Goroutinen verbrauchen von jobs <-chan T, produzieren auf results chan<- R.
  • Pipeline: Stufen, die durch Kanäle verbunden sind.
  • Fertigsignal: ein chan struct{}-Kanal geschlossen, um „Stopp“ zu signalisieren.
Go
done := make(chan struct{})
go func() {
    <-done    // blocca finché qualcuno chiude done
    cleanup()
}()
close(done)   // segnale di stop

chan struct{} ist der „Signal“-Kanal: nur null Byte Nutzlast Synchronisation.

Probieren Sie es aus

Übung#go.m7.l2.e1
Versuche: 0Wird geladen…

Erstellen Sie einen ungepufferten int-Kanal ch, senden Sie 42 von einer Goroutine, empfangen Sie ihn in main und drucken Sie ihn aus.

Editor wird geladen…
Hinweis anzeigen

Ohne Puffer synchronisieren sich Sender und Empfänger.

Lösung nach 3 Versuchen verfügbar

Übung#go.m7.l2.e2
Versuche: 0Wird geladen…

Senden Sie 1,2,3 über einen gepufferten Kanal, schließen Sie ihn und drucken Sie dann alles mit for-range aus.

Editor wird geladen…
Hinweis anzeigen

`for range` über einen Kanal endet, wenn der Kanal geschlossen und geleert wird.

Lösung nach 3 Versuchen verfügbar

Quiz#go.m7.l2.e3
Bereit

Was macht ein UNBUFFERED-Kanal, wenn der Sender sendet, aber kein Empfänger bereit ist?

Go
ch := make(chan int)
ch <- 1 // ?
Antwortoptionen

Zusammenfassung

  • Kanal = typisierte FIFO-Warteschlange, sicher zwischen Goroutinen.
  • Ungepuffert: Rendezvous (Sender und Empfänger synchronisieren).
  • Gepuffert: Entkopplung, blockiert nur bei Voll/Leer.
  • close(ch): nur der Absender; for range verbraucht bis zum Schließen.
  • Direktionalität: chan<- T (nur Senden), <-chan T (nur Empfangen).
  • chan struct{} als Signalkanal für reine Synchronisation.