Java转Go—16Select

select

select 是 go 语言中的一种条件控制语句,类似于之前学习的 switch 条件控制语句,不同的是 select 只能用于通道的控制,在 select 中同样可以有多个 case 分支和一个 default 分支,但是每一个 case 必须都是 channel 的操作,可以是发送也可以是接收,select 会一直等待,直到某一个 case 分支的 channel 操作完成之后就执行对应的代码语句。

基本语法:

select {
    case channel 语句 1 :
       // 匹配到 channel 语句 1 则执行该内容
    case channel 语句 2 :
       // 匹配到 channel 语句 1 则执行该内容
    default : // 默认执行
       // default 内容
}

select 同时监听多个分支,一直堵塞直到其中一个分支完成 channel

代码示例:

package main

import (
 "fmt"
)

func main() {
 intChan := make(chan int)
 stringChan := make(chan string)

 go func(ch chan int) {
  time.Sleep(time.Second * 2)
  ch <- 1
 }(intChan)

 go func(ch chan string) {
  time.Sleep(time.Second)
  ch <- "a"
 }(stringChan)

 select {
 case i := <- intChan:  // 监听 intChan 的操作
  fmt.Println(i)
 case s := <- stringChan: // 监听 stringChan 的操作
  fmt.Println(s)
 }
}

上述代码中的 select 有两个 case 分支,分别监听了 intChan 和 stringChan 两个通道,然后在程序中启动两个 goroutine 分别对这两个通道发送数据,则 select 会一直堵塞,直到其中一个 case 的 channel 接收到数据就执行其对应的输出语句,由于在往 intChan 中发送数据之前有两秒钟的睡眠时间, stringChan 只有一秒钟的睡眠时间,所以当前代码中永远都是 stringChan 先好,最后的结果则是在控制台打印字母 a。

在 select 中增加 default 语句后则不会一直堵塞等待

代码示例:

select {
    case i := <- intChan:
     fmt.Println(i)
    case s := <-stringChan:
     fmt.Println(s)
    default:
     fmt.Println("default操作")
}

在保持上面代码都不变的情况下,仅在 select 语句的最后加入一个 default 分支,这样再次运行代码就会打印输出 default操作,这是因为在 select 语句中加入 default 之后就不会堵塞等待,而且在 intChan 和 stringChan 中分别有一秒和两秒的沉睡,当执行到 select 语句时,两个 channel 都没有准备好,就会直接执行 default 分支的内容。

当多个 channel 同时准备好时,随机执行其中一个

代码示例:

package main

import (
 "fmt"
 "time"
)

func main() {
 intChan := make(chan int)
 stringChan := make(chan string)

 go func(ch chan int) {
  ch <- 1
 }(intChan)

 go func(ch chan string) {
  ch <- "a"
 }(stringChan)

 time.Sleep(time.Second)  // 睡眠一秒钟,确保两个 channel 都准备好

 select {
 case i := <- intChan:
  fmt.Println(i)
 case s := <-stringChan:
  fmt.Println(s)
 }
}

上面的代码中,在 select 语句之前睡眠了一秒钟,用于确保前面两个 goroutine 都执行完毕并把数据发送到 channel 中,然后再执行后面的 select 语句,这时候执行到 select 语句时,intChan 和 stringChan 都是准备就绪状态,则这时候 select 会随机选择一个 case 分支执行,所以在最后的输出结果中会随机在控制台打印数字 1 或者字母 a。

select 总结:

  1. 每一个 case 都必须是一个通道操作。
  2. 没有 default 分支时,select 会堵塞,有 default 分支时直接执行 default 分支内容。
  3. 如果有多个 case 分支同时准备就绪,则随机执行其中一个,其他的则忽略。


原文始发于微信公众号(良猿):Java转Go—16Select

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/215796.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!