select は、Goのチャンネルを操作するための強力な構文です。複数のチャンネルからのデータの受信や、チャンネルの閉鎖を待機することができます。一度に一つのケースが準備が整うと、そのケースが実行され、他のケースは現在のイテレーションでは無視されます。
ch1 := make(chan int) ch2 := make(chan string) go func() { ch1 <- 42 }() go func() { ch2 <- "hello" }() select { case i := <-ch1: fmt.Println("ch1から受信:", i) case s := <-ch2: fmt.Println("ch2から受信:", s) default: fmt.Println("通信なし") }
細かい点:
selectでどのチャンネルも読み取り/書き込みが準備できておらず、defaultブロックが存在しない場合はどうなりますか?
回答: Selectは、いずれかのチャンネルが操作の準備が整うまでブロックされます。
物語
開発者は、defaultブロックなしでselectを介してデータストリームを中断する関数を実装しましたが、関数は「管理を放棄」することを期待していました。チャンネルは空のままで、関数はselectで永遠にブロックされてストリームがハングしました。
物語
いくつかのチャンネルでselectを使用していましたが、いくつかのgoroutineでチャンネルが閉じられる際にパニックが発生し、これによりメモリリークやクラッシュが発生しました。チャンネルの閉鎖チェック(ok変数を通じて)が行われていませんでした。
物語
あるプロジェクトでは、ブロックを避けるためにselectにdefaultブロックを追加しました。しかし、これによりビジーループが発生し、selectがループで実行され、defaultが即座にヒットし、プロセッサが100%に達しました。チャンネルからのイベントを待つのではなく。