Wenn ein Kanal gepuffert ist, bedeutet dies, dass er erst blockiert wird, wenn der Puffer voll ist. Sobald der Puffer voll ist, blockiert die sendende Goroutine, wenn es versucht, den Kanal hinzuzufügen.
Dies bedeutet, dass dies blockiert wird:
c := make(chan int)
c <- 1 // Block here, this is unbuffered !
println(<-c)
Und das wird Auch Block:
c := make(chan int, 2)
c <- 1
c <- 2
c <- 3 // Block here, buffer is full !
println(<-c)
Aber die Punkt von Goroutines und Kanal ist genau, um die Dinge gleichzeitig auszuführen, daher wird dies funktionieren:
c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c) // ... this line is reached in the main goroutine
Und ähnlich:
c := make(chan int, 2)
go func() { // `go ...` spawns a goroutine
c <- 1 // Buffer is not full, no block
c <- 2 // Buffer is not full, no block
c <- 3 // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine
In Ihrem Beispiel spawnen Sie vier verschiedene Goroutinen, die alle vier Zahlen in denselben gepufferten Kanal schreiben. Da der Puffer 2 <16 ist, werden sie am Ende blockieren
Aber der Kern der Sache ist, dass die GO -Richtlinie darauf ist Warten Sie nur auf die Haupt -Goroutine:
Die Programmausführung beginnt mit der Initialisierung des Hauptpakets und dann auf die Funktion der Funktion. Wenn die Funktion der Funktion zurückgibt, verlässt das Programm. Es wartet nicht, dass andere (Nicht-Main-) Goroutinen abgeschlossen sind.
Dies bedeutet, dass in Ihrem ersten Beispiel die hauptsächlich Goroutine blockierte, als sie die Linie erreichte c <- 3
. Da keine andere Goroutine etwas tun konnte, was möglicherweise entsperren konnte, erkannte die Laufzeit, dass das Programm abgestimmt war und einen Fehler gemeldet hatte.
In Ihrem zweiten Beispiel jedoch, hervorgebracht Goroutines blockiert, während die Hauptdauer ruhig fortgesetzt wird, bis sie das Ende seiner Ausführung erreicht. Zu diesem Zeitpunkt werden alle (blockierten) Goroutinen still getötet, und es wird kein Fehler gemeldet.