Go 语言中的 select
语句用于监控并选择一组case
语句执行相应的代码。它看起来类似于switch
语句,但是select
语句中所有case
中的表达式都必须是channel
的发送或接收操作。一个典型的select
使用示例如下:
select { case <-ch1: fmt.Println("xxx.com") case ch2 <- 1: fmt.Println("xiaoman") }
Go 语言中的 select
关键字也能够让当前 goroutine
同时等待ch1
的可读和ch2
的可写,在ch1
和ch2
状态改变之前,select
会一直阻塞下去,直到其中的一个 channel
转为就绪状态时执行对应case
分支的代码。如果多个channel
同时就绪的话则随机选择一个case
执行。
除了上面展示的典型示例外,接下来我们逐一介绍一些select
的特殊示例。
空select
空select
指的是内部不包含任何case
,例如:
select{ }
空的 select
语句会直接阻塞当前的goroutine
,使得该goroutine
进入无法被唤醒的永久休眠状态。
只有一个case
如果select
中只包含一个case
,那么该select
就变成了一个阻塞的channel
读/写操作。
select { case <-ch1: fmt.Println("xxxx.com") }
上面的代码,当ch1
可读时会执行打印操作,否则就会阻塞。
有default语句
如果select
中还可以包含default
语句,用于当其他case
都不满足时执行一些默认操作。
select { case <-ch1: fmt.Println("xxx.com") default: time.Sleep(time.Second) }
上面的代码,当ch1
可读时会执行打印操作,否则就执行default
语句中的代码,这里就相当于做了一个非阻塞的channel
读取操作。
最后总结一下:
select
不存在任何的case
:永久阻塞当前 goroutineselect
只存在一个case
:阻塞的发送/接收select
存在多个case
:随机选择一个满足条件的case
执行select
存在default
,其他case
都不满足时:执行default
语句中的代码