select è una potente costrutto di Go per lavorare con i canali. Permette di attendere il ricevimento di dati da più canali o la loro chiusura. Non appena uno dei casi è pronto, viene eseguita la corrispondente branca, mentre gli altri vengono ignorati nell'iterazione corrente.
ch1 := make(chan int) ch2 := make(chan string) go func() { ch1 <- 42 }() go func() { ch2 <- "hello" }() select { case i := <-ch1: fmt.Println("ricevuto da ch1:", i) case s := <-ch2: fmt.Println("ricevuto da ch2:", s) default: fmt.Println("nessuna comunicazione") }
Dettagli:
Cosa succede se in select nessun canale è pronto per la lettura/scrittura e manca il blocco default?
Risposta: Select sarà bloccato fino a quando uno dei canali non sarà pronto per l'operazione.
Storia
Uno sviluppatore ha implementato una funzione di interruzione del flusso di dati tramite select senza un blocco default, presupponendo che la funzione "cederà il controllo" dopo alcuni tentativi. I canali sono rimasti vuoti e la funzione è rimasta bloccata in select, causando l'impasse dei flussi di dati del microservizio.
Storia
È stato usato select con più canali, in alcune goroutine si sono verificate delle paniche durante la chiusura dei canali, non gestite in select, portando a perdite e arresti anomali. Non è stata prevista una verifica sulla chiusura del canale (tramite la variabile ok).
Storia
In uno dei progetti, gli sviluppatori hanno aggiunto un blocco default in select per evitare bloccaggi. Ma ciò ha portato a un busy loop: select veniva eseguito in un ciclo, il default scattava immediatamente e il processore era carico al 100%, invece di attendere eventi dai canali.