select is een krachtige constructie in Go voor het werken met kanalen. Het maakt het mogelijk om te wachten op gegevens uit meerdere kanalen of hun sluiting. Zodra een van de cases gereed is, wordt de overeenkomstige tak uitgevoerd en worden de andere genegeerd in de huidige iteratie.
ch1 := make(chan int) ch2 := make(chan string) go func() { ch1 <- 42 }() go func() { ch2 <- "hello" }() select { case i := <-ch1: fmt.Println("ontvangen van ch1:", i) case s := <-ch2: fmt.Println("ontvangen van ch2:", s) default: fmt.Println("geen communicatie") }
Fijne kneepjes:
Wat gebeurt er als geen van de kanalen in select klaar is om te lezen/schrijven, en de default-blok ontbreekt?
Antwoord: Select zal blokkeren totdat een van de kanalen klaar is voor de operatie.
Verhaal
Een ontwikkelaar implementeerde een functie om de datastroom te onderbreken via select zonder default-blok, in de veronderstelling dat de functie "beheer zou loslaten" na enkele pogingen. De kanalen bleven leeg, en de functie blokkeerde blijvend in select, wat leidde tot het vastlopen van de datastromen van de microservice.
Verhaal
Select werd gebruikt met meerdere kanalen, waarbij enkele goroutines paniek veroorzaakten bij het sluiten van kanalen die niet in select werden verwerkt, wat leidde tot geheugenlekken en crashes. Er was geen controle op het sluiten van het kanaal (via de variabele ok).
Verhaal
In een van de projecten voegden ontwikkelaars een default-blok toe in select om blokkades te voorkomen. Maar dit leidde tot een busy loop - select werd in een lus uitgevoerd, de default werd onmiddellijk geactiveerd, en de CPU werd tot 100% belast in plaats van te wachten op gebeurtenissen van de kanalen.