select to potężna konstrukcja w Go do pracy z kanałami. Pozwala na oczekiwanie na dane z kilku kanałów lub ich zamknięcie. Gdy jeden z przypadków jest gotowy, wykonuje się odpowiednia gałąź, a pozostałe są ignorowane w bieżącej iteracji.
ch1 := make(chan int) ch2 := make(chan string) go func() { ch1 <- 42 }() go func() { ch2 <- "hello" }() select { case i := <-ch1: fmt.Println("odebrane z ch1:", i) case s := <-ch2: fmt.Println("odebrane z ch2:", s) default: fmt.Println("brak komunikacji") }
Szczegóły:
Co się stanie, jeśli w select żaden kanał nie jest gotowy do odczytu/zapisu, a blok default jest nieobecny?
Odpowiedź: Select będzie blokować, aż jeden z kanałów będzie gotowy do operacji.
Historia
Programista zaimplementował funkcję przerywania strumienia danych przez select bez bloku default, zakładając, że funkcja "zwolni kontrolę" po kilku próbach. Kanały pozostały puste, a funkcja zablokowała się na zawsze w select, prowadząc do zawieszenia strumieni danych mikroserwisu.
Historia
Użyli select z wieloma kanałami, w niektórych goroutine występowały paniki przy zamykaniu kanałów, które nie były obsługiwane w select, co prowadziło do wycieków i awarii. Nie przewidziano sprawdzenia na zamknięcie kanału (przez zmienną ok).
Historia
W jednym z projektów programiści dodali blok default do select, aby uniknąć zablokowań. Ale to doprowadziło do busy loop – select był wykonywany w pętli, blok default działał natychmiast, a procesor był obciążony w 100%, zamiast czekać na zdarzenia z kanałów.