Wie funktioniert channel blocking arbeiten Gehen?
Ich Lerne das Gehen, die Sprache. Hier ist ein Beispiel, das ich begegnet bin. Kann mir bitte jemand erklären, was hier passiert?
package main
import "time"
import "fmt"
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
go func() {
time.Sleep(time.Second * 2)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
default:
fmt.Println("Default")
}
}
}
Ausgabe:
Default
Default
Program Exited
Wenn ich den Kommentar aus dem "Standard"
//default:
// fmt.Println("Default")
die Ausgabe wird:
received one
received two
Program exited.
Wie beeinflusst die Anwesenheit des default
Fall ändern die Art und Weise Kanal-Blockierung funktioniert?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist im Zusammenhang damit, wie
select
Aussagen arbeiten Gehen.Vom die Dokumentation Gehen Sie auf
select
:Also ohne einen default-Fall, wird der code gesperrt wird, bis einige Daten zur Verfügung stehen-entweder in einem der Kanäle. Es implizit, wartet auf die anderen goroutines aufwachen und schreiben Sie Ihre Kanal.
Wenn Sie hinzufügen, die standardmäßig der Fall ist, ist es sehr wahrscheinlich, dass die
select
- Anweisung erreicht wird, bevor die anderen goroutines aufwachen vom schlafen ab.So, da keine Daten vorhanden (noch), und es gibt einen default-Fall, der default-Fall wird ausgeführt. Ist dies zweimal getan, und es dauert weniger als 1 Sekunde. Also das Programm endet mit Abbruch, bevor der go-Routinen haben die chance, aufzuwachen und zu schreiben, um den Kanal.
Beachten Sie, dass dies technisch eine race-Bedingung; es gibt absolut keine Garantie, dass die 2 Iterationen der Schleife wird ausgeführt, bevor die go-Routinen aufwachen, also in der Theorie ist es möglich, einen anderen Ausgang auch mit einem Standard-Fall, aber in der Praxis ist es sehr unwahrscheinlich.
Den
select
- Anweisung blockiert, bis mindestens ein Fall ist bereit. Die Go language specification liest, teilweise:In der original code, der
default
Fall bereit ist, auf beiden Iterationen der Schleife, da es eine Verzögerung, bevor etwas gesendet wird, aufc1
oderc2
.Nachdem Sie entfernen die
default
Fall, dieselect
- Anweisung muss warten, bis Daten zur Verfügung stehen inc1
oderc2
.default
Fall bereit ist, auf beiden Iterationen der Schleife, da es eine Verzögerung, bevor etwas gesendet wird, aufc1
oderc2
."https://tour.golang.org/concurrency/5
https://tour.golang.org/concurrency/6
Siehe die links oben für die Ausführung der Beispiele. Der default-Fall wird ausgeführt, wenn kein anderer Fall fertig ist.
wählen Sie in golang blockiert, bis einer der Fälle bereit ist. Daher entfernen Standard gemacht, die Ausführung von anderen Fällen möglich, sonst er derjenige war, der bereit war, vor den anderen