前言

作为一门现代语言,go语言实现了对并发的原生支持。如果现在要对channel进行控制,从语言层面上来说,select语句是必不可少的部分,今天我们就对select语句的行为和使用做一些讨论。

select的使用示例

为了便于理解,我们首先给出一个代码片段:

  1. select {
  2. case v1 := <-c1:
  3. fmt.Printf("received %v from c1\n", v1)
  4. case v2 := <-c2:
  5. fmt.Printf("received %v from c2\n", v1)
  6. case c3 <- 23:
  7. fmt.Printf("sent %v to c3\n", 23)
  8. default:
  9. fmt.Printf("no one was ready to communicate\n")
  10. }

上面这段代码中,select语句中有四个case子语句,前两个receive操作,第三个send操作,最后一个是默认操作。代码执行到select时,case语句会按照源代码的顺序来评估(评估这个词,感觉不是很专业??),并且只是评估一次,评估的结果会出现下面四种情况:

  1. 除default外,如果只有一个case语句评估通过,那么就执行这个case里面的语句
  2. 除default外,如果有多个case语句评估通过,那么就通过伪随机的方式随机选一个(随机的方式是怎么样的?)
  3. 如果default外的case语句都没有通过评估,那么执行defalut里的语句
  4. 如果没有default,那么代码块会被阻塞,直到有一个case通过评估,否则会一直阻塞

设置超时时间

我们希望设置某个模块的超时时间,下面是简单的demo:

  1. func main() {
  2. var c chan int
  3. timeout := time.After(5 * time.Second)
  4. for{
  5. select {
  6. case s := <-c:
  7. fmt.Println(s)
  8. case <-timeout:
  9. fmt.Println("You talk too much.")
  10. return
  11. }
  12. }
  13. }

参考:
Go语言并发模型:使用 select