select ist ein leistungsfähiges Konstrukt in Go zur Arbeit mit Kanälen. Es ermöglicht das Warten auf das Eintreffen von Daten von mehreren Kanälen oder deren Schließung. Sobald ein Fall bereit ist, wird der entsprechende Zweig ausgeführt, während die anderen in der aktuellen Iteration ignoriert werden.
ch1 := make(chan int) ch2 := make(chan string) go func() { ch1 <- 42 }() go func() { ch2 <- "hello" }() select { case i := <-ch1: fmt.Println("empfangen von ch1:", i) case s := <-ch2: fmt.Println("empfangen von ch2:", s) default: fmt.Println("keine Kommunikation") }
Details:
Was passiert, wenn in select kein Kanal zum Lesen/Schreiben bereit ist und der Default-Block fehlt?
Antwort: Select wird blockiert, bis einer der Kanäle bereit für die Operation ist.
Geschichte
Ein Entwickler implementierte eine Funktion zum Unterbrechen eines Datenstroms über select ohne Default-Block in der Annahme, dass die Funktion nach mehreren Versuchen "die Kontrolle abgeben würde". Die Kanäle blieben leer und die Funktion blockierte für immer in select, was zu einem Hängemuster des Datenstroms des Mikrodienstes führte.
Geschichte
Select wurde mit mehreren Kanälen verwendet, in einigen Goroutinen trat ein Panic auf, als die Kanäle geschlossen wurden, die im select nicht verarbeitet wurden, was zu Lecks und Abstürzen führte. Es wurde keine Überprüfung auf das Schließen des Kanals (über die Variable ok) vorgenommen.
Geschichte
In einem der Projekte fügten die Entwickler einen Default-Block in select ein, um Blockaden zu vermeiden. Dies führte jedoch zu einer Busy-Loop – select wurde in einer Schleife ausgeführt, der Default wurde sofort ausgelöst und die CPU wurde zu 100 % ausgelastet, anstatt auf Ereignisse von den Kanälen zu warten.