• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    Go 语言中的select语句详解及工作原理

    发布者: 涵韵3588 | 发布时间: 2025-8-14 13:25| 查看数: 35| 评论数: 0|帖子模式

    Go 语言中的 select 是做什么的

    在 Go 语言中,
    1. select
    复制代码
    语句是用于处理多个通道(channel)操作的一种控制结构。它类似于
    1. switch
    复制代码
    语句,但专门用于并发编程,允许 Goroutine 在多个通道上等待操作(发送或接收),并在某个通道就绪时执行对应的分支。
    1. select
    复制代码
    是 Go 并发模型中的核心特性之一,与通道和 Goroutine 紧密相关。

    基本功能
    1. select
    复制代码
    的主要作用是:

    • 多路复用通道:同时监听多个通道的读写操作。
    • 非阻塞选择:当多个通道中有任意一个就绪时,执行对应的逻辑;如果没有通道就绪,可以执行默认分支(如果有)。
    • 并发协调:帮助 Goroutine 在不同的通信场景中协调行为。

    语法
    1. select {
    2. case <-channel1:
    3.     // 从 channel1 接收数据时的处理逻辑
    4. case channel2 <- value:
    5.     // 向 channel2 发送数据时的处理逻辑
    6. case v := <-channel3:
    7.     // 从 channel3 接收数据并赋值给 v 的处理逻辑
    8. default:
    9.     // 所有通道都未就绪时的默认逻辑(可选)
    10. }
    复制代码

    • 每个
      1. case
      复制代码
      表示一个通道操作(发送或接收)。
      1. default
      复制代码
      是可选的,表示当所有通道都未就绪时执行的逻辑。

    工作原理

    等待通道就绪

      1. select
      复制代码
      会阻塞当前 Goroutine,直到某个
      1. case
      复制代码
      中的通道操作可以执行。
    • 如果多个通道同时就绪,
      1. select
      复制代码
      会随机选择一个
      1. case
      复制代码
      执行(避免饥饿问题)。
    非阻塞行为

    • 如果提供了
      1. default
      复制代码
      分支,且没有通道就绪,
      1. select
      复制代码
      会立即执行
      1. default
      复制代码
      而不会阻塞。
    空 select

    • 如果
      1. select
      复制代码
      中没有
      1. case
      复制代码
      ,会永久阻塞(类似于
      1. for {}
      复制代码
      )。

    示例


    示例 1:监听多个通道
    1. package main
    2. import (
    3.     "fmt"
    4.     "time"
    5. )
    6. func main() {
    7.     ch1 := make(chan string)
    8.     ch2 := make(chan string)
    9.     go func() {
    10.         time.Sleep(1 * time.Second)
    11.         ch1 <- "from ch1"
    12.     }()
    13.     go func() {
    14.         time.Sleep(2 * time.Second)
    15.         ch2 <- "from ch2"
    16.     }()
    17.     select {
    18.     case msg1 := <-ch1:
    19.         fmt.Println("Received:", msg1)
    20.     case msg2 := <-ch2:
    21.         fmt.Println("Received:", msg2)
    22.     }
    23. }
    复制代码

    • 输出
      1. Received: from ch1
      复制代码
    • 说明
      1. ch1
      复制代码
      在 1 秒后就绪,比
      1. ch2
      复制代码
      (2 秒)快,因此执行
      1. ch1
      复制代码
      的分支。

    示例 2:带默认分支
    1. package main
    2. import (
    3.     "fmt"
    4. )
    5. func main() {
    6.     ch := make(chan string)
    7.     select {
    8.     case msg := <-ch:
    9.         fmt.Println("Received:", msg)
    10.     default:
    11.         fmt.Println("No message received")
    12.     }
    13. }
    复制代码

    • 输出
      1. No message received
      复制代码
    • ​​​​​​​说明:由于
      1. ch
      复制代码
      没有数据就绪,
      1. select
      复制代码
      执行
      1. default
      复制代码
      分支。

    示例 3:发送和接收结合
    1. package main
    2. import (
    3.     "fmt"
    4.     "time"
    5. )
    6. func main() {
    7.     ch1 := make(chan string, 1)
    8.     ch2 := make(chan string, 1)
    9.     select {
    10.     case ch1 <- "to ch1":
    11.         fmt.Println("Sent to ch1")
    12.     case msg := <-ch2:
    13.         fmt.Println("Received from ch2:", msg)
    14.     default:
    15.         fmt.Println("Nothing happened")
    16.     }
    17. }
    复制代码

    • 输出
      1. Sent to ch1
      复制代码
    • ​​​​​​​说明
      1. ch1
      复制代码
      是缓冲通道,可以立即发送成功,因此执行发送分支。

    示例 4:超时控制
    1. package main
    2. import (
    3.     "fmt"
    4.     "time"
    5. )
    6. func main() {
    7.     ch := make(chan string)
    8.     select {
    9.     case msg := <-ch:
    10.         fmt.Println("Received:", msg)
    11.     case <-time.After(2 * time.Second):
    12.         fmt.Println("Timeout after 2 seconds")
    13.     }
    14. }
    复制代码

    • 输出
      1. Timeout after 2 seconds
      复制代码
    • ​​​​​​​说明
      1. time.After
      复制代码
      创建一个定时器通道,2 秒后就绪,模拟超时逻辑。

    常见用途

    多路复用
    在多个通道之间选择就绪的通道,避免逐一轮询。
    超时处理
    使用
    1. time.After
    复制代码
    实现操作超时。
    非阻塞检查
    通过
    1. default
    复制代码
    分支检查通道是否就绪。
    协调 Goroutine
    在并发任务中,根据通道状态决定下一步操作。

    注意事项

    随机选择
    当多个
    1. case
    复制代码
    同时就绪时,
    1. select
    复制代码
    随机选择一个执行,而不是按顺序。
    阻塞性
    没有
    1. default
    复制代码
    时,
    1. select
    复制代码
    会阻塞直到某个通道就绪。
    空 select
    1. select {}
    复制代码
    这会永久阻塞,通常用于主 Goroutine 等待。
    通道关闭
    如果某个通道已关闭,接收操作会立即返回零值,可能需要额外的逻辑判断。

    总结


    • 是什么
      1. select
      复制代码
      是 Go 中用于处理多通道操作的并发控制语句。
    • 做什么:监听多个通道,选择就绪的通道执行对应逻辑,支持超时和非阻塞操作。
    • 为什么用:简化并发编程,提高代码效率和可读性。
    到此这篇关于Go 语言中的select是做什么的的文章就介绍到这了,更多相关Go select内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    浏览过的版块

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表