select
語句屬於條件分支流程控制方法,不過它只能用於通道。它能夠包含若干條case
語句,並根據條件選擇其中的一個執行。進一步說,select
語句中的case
關鍵字只能後跟用於通道的發送操做的表達式以及接收操做的表達式或語句。示例以下:算法
ch1 := make(chan int, 1) ch2 := make(chan int, 1) // 省略若干條語句 select { case e1 := <-ch1: fmt.Printf("1th case is selected. e1=%v.\n", e1) case e2 := <-ch2: fmt.Printf("2th case is selected. e2=%v.\n", e2) default: fmt.Println("No data!") }
若是該select
語句被執行時通道ch1
和ch2
中都沒有任何數據,那麼確定只有default case
會被執行。可是,只要有一個通道在當時有數據就不會輪到default case
執行了。顯然,對於包含通道接收操做的case
來說,其執行條件就是通道中存在數據(或者說通道未空)。若是在當時有數據的通道多於一個,那麼Go語言會經過一種僞隨機的算法來決定哪個case
將被執行。
另外一方面,對於包含通道發送操做的case
來說,其執行條件就是通道中至少還能緩衝一個數據(或者說通道未滿)。相似的,當有多個case
中的通道未滿時,它們會被隨機選擇。請看下面的示例:spa
ch3 := make(chan int, 100) // 省略若干條語句 select { case ch3 <- 1: fmt.Printf("Sent %d\n", 1) case ch3 <- 2: fmt.Printf("Sent %d\n", 2) default: fmt.Println("Full channel!") }
該條select
語句的兩個case
中包含的都是針對通道ch3
的發送操做。若是咱們把這條語句置於一個循環中,那麼就至關於用有限範圍的隨機整數集合去填滿一個通道。
請注意,若是一條select
語句中不存在default case
, 而且在被執行時其中的全部case
都不知足執行條件,那麼它的執行將會被阻塞!當前流程的進行也會所以而停滯。直到其中一個case
知足了執行條件,執行纔會繼續。咱們一直在說case
執行條件的知足與否取決於其操做的通道在當時的狀態。這裏特別強調一點,即:未被初始化的通道會使操做它的case
永遠知足不了執行條件。對於針對它的發送操做和接收操做來講都是如此。
最後提一句,break
語句也能夠被包含在select
語句中的case
語句中。它的做用是當即結束當前的select
語句的執行,不論其所屬的case
語句中是否還有未被執行的語句。code