当前位置: 首页 > news >正文

Go语言select

select是什么

   select是Go语言层面提供的一种多路复用机制,用于检测当前goroutine连接的多个channel是否有数据准备完毕,可用于读或写。

        Go语言的select语句,是用来起一个goroutine监听多个Channel的读写事件,提高从多个Channel获取信息的效率,相当于是单线程处理多个IO事件,其思想基本相同。

select的用法

select的基本使用模式如下:

select {case <- channel1:     // 如果从channel1读取数据成功,执行case语句 do ...   case channel2 <- 1:   // 如果向channel2写入数据成功,执行case语句 do ...          default:              // 如果上面都没有成功,进入default处理流程do ...
}

        可以看到,select的用法形式类似于switch,但是区别于switch的是select各个case的表达式必须都是channel的读写操作select通过多个case语句监听多个channel的读写操作是否准备好可以执行,其中任何一个case可以执行了则选择该case语句执行,如果没有可以执行的case,则执行default语句,如果没有default,则当前goroutine会阻塞。 

空select永久阻塞

当一个select中什么语句都没有,没有任何case,将会永久阻塞:

package mainfunc main() {select {}
}

运行结果:

fatal error: all goroutines are asleep - deadlock!

        程序因为select语句导致永久阻塞,当前goroutine阻塞之后,由于Go语言自带死锁检测机制,发现当前goroutine永远不会被唤醒,会报上述死锁错误。 

没有default且case无法执行的select永久阻塞

看下面示例:

package mainimport ("fmt"
)func main() {ch1 := make(chan int, 1)ch2 := make(chan int, 1)select {case <-ch1:fmt.Printf("received from ch1")case num := <-ch2:fmt.Printf("num is: %d", num)}
}

运行结果:

fatal error: all goroutines are asleep - deadlock!

        程序中 select从两个channelch1ch2中读取数据,但是两个channel都没有数据,且没有goroutine往里面写数据,所以不可能读到数据,这两个case永远无法执行到,select也没有default,所以会出现永久阻塞,报死锁。 

单一case和default的select

package mainimport ("fmt"
)func main() {ch := make(chan int, 1)select {case <-ch:fmt.Println("received from ch")default:fmt.Println("default!!!")}
}

运行结果:

default!!!

        执行到select语句的时候,由于ch中没有数据,且没有goroutinechannel中写数据,所以case不可能执行到,就会执行default语句,打印出default!!!。 

 多个case和default的select

package mainimport ("fmt""time"
)func main() {ch1 := make(chan int, 1)ch2 := make(chan int, 1)go func() {time.Sleep(time.Second)for i := 0; i < 3; i++ {select {case v := <-ch1:fmt.Printf("Received from ch1, val = %d\n", v)case v := <-ch2:fmt.Printf("Received from ch2, val = %d\n", v)default:fmt.Println("default!!!")}time.Sleep(time.Second)}}()ch1 <- 1time.Sleep(time.Second)ch2 <- 2time.Sleep(4 * time.Second)
}

运行结果:

Received from ch1, val = 1
Received from ch2, val = 2
default!!!

        主goroutine中向后往管道ch1ch2中发送数据,在子goroutine中执行两个select,可以看到,在执行select的时候,那个case准备好了就会执行当下case的语句,最后没有数据可接受了,没有case可以执行,则执行default语句。

注意当多个case都准备好了的时候,会随机选择一个执行

package mainimport ("fmt"
)func main() {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch1 <- 5ch2 <- 6select {case v := <-ch1:fmt.Printf("Received from ch1, val = %d\n", v)case v := <-ch2:fmt.Printf("Received from ch2, val = %d\n", v)default:fmt.Println("default!!!")}
}

运行结果:

Received from ch2, val = 6

多次执行,2个case都有可能打印,这就是select选择的随机性。

http://www.lryc.cn/news/610424.html

相关文章:

  • Git基础玩法简单描述
  • 【LeetCode刷题集】--排序(一)
  • ICCV2025 Tracking相关paper汇总和解读(19篇)
  • ubuntu 20.04 C和C++的标准头文件都放在哪个目录?
  • windows双系统下ubuntu20.04安装教程
  • HTTPS有哪些优点
  • Jeston + TensorRT + Realsense D435i + ROS noetic + Yolo11 各版本模型目标检测
  • Flink CDC 介绍
  • Field and wave electromagnetics 复习
  • 正点原子阿波罗STM32F429IGT6移植zephyr rtos(四)---在独立的应用工程里使用MPU6050
  • 【Java】一篇详解HashMap的扩容机制!!
  • SparkSQL—sequence 函数用法详解
  • 四、Linux 的实用操作
  • wpf Image 转 90 度
  • 华为OD机考2025C卷 - 分配土地 (Java Python JS C++ C )
  • 复合机器人抓取精度怎么测量?
  • Tableau筛选器所有值与总和的差异:同一度量,两重世界
  • 【教学类-52-17】20250803动物数独_空格尽量分散_只有一半关卡数(N宫格通用版3-10宫格)0图、1图、2图、6图、有答案、无答案 组合版24套
  • 内网有人下载导致网速很慢怎么找出来?
  • Vue3核心语法进阶(生命周期)
  • MySQL InnoDB 表数据结构存储方式详解
  • 川翔云电脑:引领开启算力无边界时代
  • 数学 理论
  • 哪些企业需要私有化部署?有没有推荐的私有化im
  • 段落注入(Passage Injection):让RAG系统在噪声中保持清醒的推理能力
  • [Shell编程] 零基础入门 Shell 编程:从概念到第一个脚本
  • 【RH124知识点问答题】第8章 监控和管理 Linux 进程
  • Linux 磁盘管理详解:分区、格式化与挂载全流程指南
  • 内联函数:提升效率的空间换时间艺术
  • C++面试题及详细答案100道( 01-10 )