📦 1. Unbuffered vs. Buffered Channels
Channels sind typsichere Kommunikationskanäle zwischen Goroutines. Sie garantieren thread-sichere Übergaben ohne manuelle Mutex-Locks.
Sender: [ch <- val] ──(Blockiert bis Empfänger bereit)──> [val := <-ch] : Empfänger
[Buffered: Asynchrone Warteschlange, Kapazität: 3]
Sender: [ch <- val] ──> [ [Slot 1] [Slot 2] [Slot 3] ] ──> [val := <-ch] : Empfänger
(Blockiert erst wenn Puffer voll ist)
// 1. Unbuffered Channel (Kapazität 0): Synchroner Rendezvous-Punkt
ch := make(chan int)
// 2. Buffered Channel (Kapazität N): Asynchroner Ringpuffer
bufferedCh := make(chan string, 5)
// 3. Senden und Empfangen:
bufferedCh <- "Event 1" // Schreibt in Puffer (nicht-blockierend solange Puffer < 5)
msg := <-bufferedCh // Liest aus Puffer ("Event 1")
// 4. Prüfen ob Channel noch offen ist (Comma-OK Idiom):
val, ok := <-bufferedCh
if !ok {
fmt.Println("Channel wurde geschlossen!")
}
🔄 2. Channel-Direktionen & Pipeline-Pattern
In Funktionssignaturen schränken wir Kanäle auf Send-Only (chan<- T) oder Receive-Only (<-chan T) ein. Das verhindert unbeabsichtigtes Schließen oder Lesen zur Compile-Zeit!
// Producer darf nur in den Channel schreiben und ihn schließen
func Produce(out chan<- int) {
for i := 1; i <= 3; i++ {
out <- i * 10
}
close(out) // ⚠️ WICHTIG: Nur der SENDER schließt den Channel!
}
// Consumer darf nur aus dem Channel lesen
func Consume(in <-chan int) {
// Liest automatisch bis close(in) ausgeführt wird:
for val := range in {
fmt.Println("Empfangen:", val)
}
}
Stell dir ein Fließband in einer Fabrik vor:
Goroutine 1 (Producer) legt Bauteile auf das Band. Ein ungepuffertes Band stoppt sofort, wenn am anderen Ende niemand steht, um das Teil entgegenzunehmen. Ein gepuffertes Band (Kapazität 5) kann 5 Teile zwischenlagern. Sobald die Schicht vorbei ist, schaltet der Producer die Signallampe aus (close(ch)) und der Consumer weiß, wann die Arbeit getan ist.
📑 3. Cheat-Sheet: Channel Operationen & Panics
| Operation | Offener Channel | Geschlossener Channel (closed) | Nil Channel (nil) |
|---|---|---|---|
Senden (ch <- v) |
Erfolgreich (blockiert wenn voll) | 💥 PANIC (send on closed channel) | ⏳ Blockiert für immer |
Empfangen (v := <-ch) |
Liefert Wert (blockiert wenn leer) | Liefert Zero-Value & ok=false |
⏳ Blockiert für immer |
Schließen (close(ch)) |
Erfolgreich | 💥 PANIC (close of closed channel) | 💥 PANIC (close of nil channel) |
🧠 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
Die Goroutine, die einen Channel erstellt und befüllt, ist der Owner. Nur der Owner sollte in den Channel schreiben und ihn mit close() schließen. Consumer sollten niemals fremde Channels schließen!