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