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

GoLang的select是什么?在什么时候场景下用

在 Go 语言中,select 是专门用于处理通道(Channel)多路复用的关键字,它可以同时监听多个通道的读写操作,并根据就绪的通道执行对应的逻辑。以下是 select 的用法和典型应用场景:

一、基本用法

select 语法类似于 switch,但每个 case 必须是一个通道操作(发送或接收)。select 会阻塞,直到某个 case 对应的通道操作就绪,然后执行该 case 的代码。如果有多个 case 同时就绪,会随机选择一个执行。

select {
case data := <-ch1:  // 监听 ch1 的接收操作
    fmt.Println("Received from ch1:", data)
case ch2 <- 42:      // 监听 ch2 的发送操作
    fmt.Println("Sent to ch2")
case <-time.After(1 * time.Second):  // 超时控制
    fmt.Println("Timeout")
}

文章目录

    • 一、基本用法
    • 二、核心应用场景
        • 1. 多通道监听
        • 2. 超时控制
        • 3. 任务取消(Cancellation)
        • 4. 非阻塞操作(Default Case)
        • 5. 并发任务协调

二、核心应用场景

1. 多通道监听
select {
case res := <-api1Chan:
    fmt.Println("API1 response:", res)
case res := <-api2Chan:
    fmt.Println("API2 response:", res)
}
2. 超时控制

场景:避免某个通道操作永久阻塞,强制结束长时间未响应的操作。

示例:结合 time.After 实现超时逻辑。

select {
case data := <-ch:
    fmt.Println("Received:", data)
case <-time.After(3 * time.Second):
    fmt.Println("Timeout: No data received")
}

三、执行流程

  1. 当执行到 select 语句时,它会监听页面 case 中的两个通道操作:从 ch 接收数据和从 time.After 返回的通道接收数据。

  2. 如果此时通道 ch 中有数据发送,那么第一个分支会被执行,接收到数据并打印,然后 select 语句结束。

  3. 如果通道 ch 中没有数据发送,那么 select 会等待,直到 3 秒后 time.After 返回的通道发送数据,此时第二个分支被执行,打印超时信息,select 语句结束。

  4. 如果在等待过程中,通道 ch 收到数据的时间刚好在 3 秒内,那么第一个分支会优先执行,因为一旦有通道操作可以执行,select 就会选择执行对应的分支,而不会等待其他分支的操作完成。

这种代码结构在处理需要等待某个事件发生,同时又不想无限期等待的场景时非常有用,比如在网络编程中等待服务器响应、在并发任务中等待某个任务完成等场景,可以有效地避免程序因某个操作长时间没有响应而陷入死等状态。

3. 任务取消(Cancellation)

场景:通过监听一个取消通道(如 context.Done()),主动终止协程。

示例:使用 context 实现优雅退出。

# 定时5秒后结束
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

select {
case <-ctx.Done():
    fmt.Println("Operation cancelled:", ctx.Err())
case result := <-workChan:
    fmt.Println("Work completed:", result)
}
4. 非阻塞操作(Default Case)

场景:尝试发送或接收数据,若无法立即执行,则执行默认逻辑。

示例:非阻塞读取通道。

select {
case data := <-ch:
    fmt.Println("Data received:", data)
default:
    fmt.Println("No data available")
}
5. 并发任务协调

场景:等待多个并发任务完成,收集第一个结果或全部结果。

示例:等待多个服务返回,取最快的结果。

ch1 := make(chan string)
ch2 := make(chan string)

go fetchFromService1(ch1)
go fetchFromService2(ch2)

select {
case res := <-ch1:
    fmt.Println("Result from Service1:", res)
case res := <-ch2:
    fmt.Println("Result from Service2:", res)
}

http://www.kler.cn/a/574062.html

相关文章:

  • Unity多Pass渲染与GPU Instancing深度优化指南
  • OpenCV计算摄影学(16)调整图像光照效果函数illuminationChange()
  • 浅谈Manus智能体与其他AI助手(如ChatGPT、Claude等)的优势
  • 【C++进阶学习】第一讲——继承(下)---深入挖掘继承的奥秘
  • JS—组成:2分钟掌握什么是ECMAScript操作,什么是DOM操作,什么是BOM操作
  • 利用Python爬虫获取17网(17zwd)商品详情:实战指南
  • MySQL学习笔记(3)InnoDB存储引擎对MVCC的实现
  • 计算机毕业设计SpringBoot+Vue.js青年公寓服务平台(源码+文档+PPT+讲解)
  • 深度学习中TorchScript原理、作用浅析(Trace/Script)
  • MySQL事务,函数,性能,索引
  • 【GoTeams】-2:项目基础搭建(下)
  • BGP服务器主要是指什么?
  • 硬件学习【1】74HC165D-并行信号输入-串行输出
  • VSCode 配置优化指南:打造极致高效的前端开发环境
  • 系统架构设计师—软件工程基础篇—软件开发方法
  • 【无标题】养老护理初级考题抽取——2大题抽1+7小题抽2-共有432种可能。
  • 【LeetCode 热题 100】438. 找到字符串中所有字母异位词 | python 【中等】
  • go语言因为前端跨域导致无法访问到后端解决方案
  • vim基本操作及常用命令
  • WPS条件格式:B列的值大于800,并且E列的值大于B列乘以0.4时,这一行的背景标红