select 语义
select 从一组发送或者接受操作中选择一个操作进行处理。类似于switch,但是其中的操作全都是有关channel通信的。
select 处理的步骤如下
如果有一个或多个通信操作可以处理,将随机的选择一个进行处理;除此之外如果有default,则处理default case, 没有default case select就会阻塞直到有一个通信操作可以处理。
如果选择的不是default case, 执行对应的通信操作。
如果选择的是一个有短变量申明或赋值的接受表达式操作,那左边的表达式会被求值, 接受到的值被赋值。
被选择的case的语句被执行。
在nil channel上的通信永远不能被处理,一个只有nil channel, 且没有default case的select将永远阻塞。也就是说,select不会选择一个nil channel做处理。
检测超时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package main
import ( "fmt" "time" )
func main() { ch := make(chan string) defer close(ch)
go func() { time.Sleep(2 * time.Second) ch <- "result" }()
select { case v := <-ch: fmt.Println(v) case <-time.After(1 * time.Second): fmt.Println("time out") } }
func timeConsumeFunc(ch chan<- string) { time.Sleep(2 * time.Second) ch <- "result" }
|
输出
判断channel是否空, 判断channnel是否满
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main
import "fmt"
func main() { var done = make(chan struct{}, 1) done <- struct{}{}
select { case done <- struct{}{}: default: fmt.Println("done chan is full") }
var ch = make(chan struct{}, 1) select { case <-ch: default: fmt.Println("ch is empty") } }
|
1 2
| done chan is full ch is empty
|