深入理解Go语言中的Channel与Select

Go 语言中的 Channel 和 Select 是并发编程中的重要概念和机制,它们为协程之间的通信和同步提供了强大的支持。接下来将深入介绍 Channel 和 Select 的概念、使用方法、特性,并结合实际工作场景和示例代码进行详细讨论。

1. Channel 概述

1.1 什么是 Channel?

Channel 是 Go 语言中用于协程之间通信的管道。它允许协程之间通过发送和接收消息来进行通信,并提供了一种同步机制,用于控制协程的执行顺序。

1.2 Channel 特性
  • 类型安全:Channel 是类型安全的,只能传递指定类型的数据。
  • 阻塞操作:发送和接收操作都是阻塞的,直到发送方发送数据,或接收方接收数据为止。
  • FIFO 队列:Channel 中的数据按照先进先出(FIFO)的顺序进行处理。
  • 关闭机制:Channel 可以被关闭,关闭后不再接收新数据,但仍可以从已关闭的 Channel 中接收数据。
1.3 Channel基本使用
1.3.1 创建channel
// 创建一个用于传递整数的 Channel
ch := make(chan int)
1.3.2 发送数据到 Channel
// 向 Channel 发送数据
ch <- 10
1.3.3 从 Channel 接收数据
// 从 Channel 接收数据
data := <-ch
1.3.4 关闭 Channel
// 关闭 Channel
close(ch)
1.4Channel 应用场景
1.4.1 并发爬虫

在网络爬虫中,可以使用 Channel 来实现并发爬取网页的功能。下面是一个简化的示例代码:

package mainimport ("fmt""net/http"
)func crawl(url string, ch chan<- string) {resp, err := http.Get(url)if err != nil {fmt.Println("Error:", err)return}defer resp.Body.Close()ch <- url
}func main() {urls := []string{"http://example.com", "http://example.org", "http://example.net"}ch := make(chan string)for _, url := range urls {go crawl(url, ch)}for i := 0; i < len(urls); i++ {fmt.Println(<-ch)}
}

在这个示例中,我们创建了一个 Channel ch 用于存储爬取到的网页 URL。然后并发地启动了多个爬虫协程,每个协程负责爬取一个网页,并将其 URL 发送到 Channel 中。最后,主协程从 Channel 中接收 URL 并打印出来。

1.4.2 工作池模式

工作池模式是一种常见的并发编程模式,可以用于控制并发任务的数量。下面是一个简单的工作池示例:

package mainimport ("fmt""sync"
)func worker(id int, jobs <-chan int, results chan<- int) {for job := range jobs {fmt.Printf("Worker %d started job %d\n", id, job)results <- job * 2fmt.Printf("Worker %d finished job %d\n", id, job)}
}func main() {const numJobs = 5jobs := make(chan int, numJobs)results := make(chan int, numJobs)var wg sync.WaitGroup// 启动多个工作者for i := 1; i <= 3; i++ {wg.Add(1)go func(workerID int) {defer wg.Done()worker(workerID, jobs, results)}(i)}// 提供工作for j := 1; j <= numJobs; j++ {jobs <- j}close(jobs)// 收集结果go func() {wg.Wait()close(results)}()// 打印结果for result := range results {fmt.Println("Result:", result)}
}

在这个示例中,我们创建了一个固定大小的工作池,并启动了多个工作者协程。然后,向工作池中发送一定数量的任务,并等待所有任务完成后,关闭结果 Channel 并打印结果。

2. Select 语句

2.1 什么是 Select?

Select 是 Go 语言中的一个控制结构,用于处理多个 Channel 上的操作。它类似于 switch 语句,但是用于 Channel 的接收操作。

2.2 Select 语法
select {
case data := <-ch1:fmt.Println("Received from ch1:", data)
case data := <-ch2:fmt.Println("Received from ch2:", data)
}

Select 语句用于在多个 Channel 上等待数据,并执行相应的操作。当有多个 Channel 同时就绪时,Select 会随机选择一个执行。

3. Channel 与 Select 的结合应用

3.1 多路复用
func main() {ch1 := make(chan int)ch2 := make(chan string)go func() {ch1 <- 1}()go func() {ch2 <- "hello"}()select {case data := <-ch1:fmt.Println("Received from ch1:", data)case data := <-ch2:fmt.Println("Received from ch2:", data)}
}

在这个示例中,我们创建了两个 Channel ch1ch2,并分别向其发送了数据。然后使用 Select 语句等待这两个 Channel 上的数据,并执行相应的操作。由于 Select 会随机选择一个就绪的 Channel,因此无论哪个 Channel 先就绪,都会打印出相应的数据。

3.2 超时处理
func main() {ch := make(chan int)timeout := time.After(1 * time.Second)select {case data := <-ch:fmt.Println("Received:", data)case <-timeout:fmt.Println("Timeout")}
}

在这个示例中,我们创建了一个 Channel ch 和一个 1 秒的超时时间。然后使用 Select 语句等待 Channel 上的数据,并设置了超时处理,当超过指定时间后,会执行相应的超时操作。

4. Channel 和 Select 的最佳实践

4.1 优雅的退出
func worker(ch <-chan bool) {for {select {case <-ch:fmt.Println("Worker exiting...")returndefault:// 执行任务...}}
}

在并发任务中,我们通常需要实现优雅的退出机制。可以通过在 Channel 上发送信号来通知协程退出,并在协程中使用 Select 来监听退出信号,实现优雅退出。

4.2 限流控制
func worker(ch <-chan int, semaphore chan struct{}) {for {select {case <-semaphore:data := <-chfmt.Println("Received:", data)}}
}

在高并发场景中,为了避免资源耗尽和性能下降,可以使用 Channel 和 Select 结合控制并发数量,实现限流控制。

5. 总结

Channel 和 Select 是 Go 语言中非常强大和灵活的并发编程工具,它们为协程之间的通信和同步提供了强大的支持。通过结合 Channel 和 Select 的使用,我们可以实现各种复杂的并发模式,如多路复用、超时处理、优雅退出和限流控制等。希望以上内容能够对大家加深对 Channel 和 Select 的理解,并能够在实际工作中发挥作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/700782.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Docker极简教程》--Docker卷和数据持久化--Docker卷的概念

在容器化环境中&#xff0c;数据持久性是一个重要挑战。传统上&#xff0c;容器是短暂的、易于销毁和重建的&#xff0c;这与数据的持久性需求相冲突。当容器被销毁时&#xff0c;容器内部的数据通常会丢失&#xff0c;因此需要一种方法来确保数据的持久性。这涉及到数据的存储…

Java基础之lambda表达式(五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

《Python 语音转换简易速速上手小册》第9章 特定领域的语音处理(2024 最新版)

文章目录 9.1 语音处理在不同行业的应用9.1.1 基础知识9.1.2 主要案例:智能客服机器人案例介绍案例 Demo案例分析9.1.3 扩展案例 1:医疗语音助手案例介绍案例 Demo案例分析9.1.4 扩展案例 2:语言学习应用案例介绍案例 Demo

Python 实现Hash算法验证

目录 一、Hash 算法的原理及作用 二、python验证Hash算法代码实现 三、运行脚本验证如下 四、在线工具验证结果如下 五、总结 一、Hash 算法的原理及作用 Hash加密算法是一种将任意长度的消息压缩成固定长度散列值的算法。它的特点是快速、不可逆和安全。对于相同的消息&a…

Java整型字符串数组

整数类型 byte&#xff0c;字节 【1字节】表示范围:-128~127即: -2^7~2^7 -1 short&#xff0c;短整型 【2字节】表示范围: -32768~32767 int&#xff0c;整型 【4字节】表示范围: -2147483648~2147483647 long,长整型 【8字节】表示范围: -9223372036854775…

陪玩软件系统的开发-用PHP书写,uni开发的陪玩平台更有质量-线上线下功能齐全-APP小程序H5公众号都有,源码交付!

线上陪玩系统的功能 在线预订&#xff1a;用户可以在陪玩系统中在线预订陪玩服务&#xff0c;系统会根据用户的订单要求自动匹配陪玩人员。 指定搜索&#xff1a;用户可以通过搜索指定的ID来找到他们想要的陪玩人员。 在线交流&#xff1a;在陪玩系统中提供在线沟通功能&…

听课笔记03

小练习 使用cmd打开qq 切换盘符 qq.exe 有简单的方法吗&#xff1f; 进入多层文件夹太麻烦了。 在任意的文件夹下打开qq 怎么做 当前目录没有qq 把qq的路径记录到电脑上 环境变量 把qq的路径记录到环境变量中 设置环境变量 高级系统设置 path里放系统路径 从上往下找 可以配置任…

Bluesky数据采集框架-1

Bluesky是一个用于实验控制和科学数据和元数据采集的库。它强调以下特点&#xff1a; 1、实时&#xff0c;流式数据&#xff1a;可用于嵌入可视化和处理。 2、丰富元数据&#xff1a;获取和组织来方便复制性和可检索性。 3、实验通用性&#xff1a;对完全不同的硬件无缝地重…

提升装备制造企业竞争力:2023年CRM选型与应用完全解读

在加快产业转型升级的大背景下&#xff0c;高端装备制造业既面临机遇也面临挑战。随着公司规模的不断壮大&#xff0c;再加上装备制造业营销体系及服务体系管理体系的复杂性&#xff0c;一些问题逐渐暴露出来&#xff0c;装备制造业企业需要根据自身业务需求和管理流程选择合适…

指针作为传入传出参数

C语言/C中&#xff0c;当函数参数为指针的时候&#xff0c;一般分为传入和传出参数&#xff1a; 指针前有const&#xff0c;认为是是传入参数&#xff1b; 指针前无const&#xff0c;一般认为是传出参数&#xff1a; 例如&#xff1a; void func(int *value)//形参前没有加…

fpga_RGB模型与硬件加速思维

一 RGB模型 人眼之所以可以看到各种颜色的光&#xff0c;主要是红绿蓝三种感光细胞综合感觉的结果&#xff0c;而红绿蓝三色被称为三原色。 饱和度均为100%的RGB能组合成8种颜色&#xff0c;计算机处理的BMP图片为24bit的位图&#xff0c;即每一通道的颜色可以组合为2的8次方&a…

训练Sora模型,你可能需要这些开源代码,模型,数据集及算力评估

在之前的文章&#xff0c;我们总结了Sora模型上用到的一些核心技术和论文 复刻大模型 Sora 有多难&#xff1f;一张图带你读懂 Sora 的技术路径一文看懂大模型 Sora 技术推演 今天这篇文章来自我们社区讨论交流&#xff0c;我这边整理和总结现有的一些开源代码、模型、数据集…

Java面试问题集锦

1.JDK、JRE、JVM 三者有什么关系&#xff1f; JDK&#xff08;全称 Java Development Kit&#xff09;&#xff0c;Java开发工具包&#xff0c;能独立创建、编译、运行程序。 JDK JRE java开发工具&#xff08;javac.exe/java.exe/jar.exe) JRE&#xff08;全称 Java Runtim…

计算机设计大赛 深度学习图像分类算法研究与实现 - 卷积神经网络图像分类

文章目录 0 前言1 常用的分类网络介绍1.1 CNN1.2 VGG1.3 GoogleNet 2 图像分类部分代码实现2.1 环境依赖2.2 需要导入的包2.3 参数设置(路径&#xff0c;图像尺寸&#xff0c;数据集分割比例)2.4 从preprocessedFolder读取图片并返回numpy格式(便于在神经网络中训练)2.5 数据预…

easyrecovery数据恢复软件14中文绿色版下载

EasyRecovery易恢复14全面介绍 一、功能概览 EasyRecovery易恢复14是一款功能强大的数据恢复软件&#xff0c;旨在帮助用户从各种存储介质中恢复丢失或删除的文件。无论是由于误删、格式化、系统崩溃还是其他未知原因导致的数据丢失&#xff0c;EasyRecovery易恢复14都能提供…

postman测试上传文件、导出excel的方法

按照如下操作步骤执行就可以了&#xff1a; 1、PostMan测试接口实现上传文件 第一步&#xff1a; 打开postman&#xff0c;将上传方式改为POST&#xff0c;再点击下【Body】 第二步&#xff1a; 然后&#xff0c;我们点击里面的【form-data】选项(如图所示)。 第三步&#xff…

蓝桥杯STAMA比赛 科学素养题 每日一题(2022年2月-2022年10月)

二月 科学素养题 在我国山东省和山西省中间的“山"是(C ) 。 A泰山 B吕梁山 C太行山 D沂蒙山。 在一些寻宝游戏中,每个线索都会指向下一个线索的位置,玩家可以顺着这些线索一个一个找到所有的元素。这样的寻宝游戏的设计与()数据结构有着异曲同工之妙。(A) A链表 B堆栈 C堆…

Vue+SpringBoot打造超市自助付款系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 商品类型模块2.2 商品模块2.3 超市账单模块 三、界面展示3.1 登录注册模块3.2 超市商品类型模块3.3 超市商品模块3.4 商品购买模块3.5 超市账单模块 四、部分源码展示4.1 实体类定义4.2 控制器接口 五、配套文档展示六、…

Java智慧工地云综合管理平台SaaS源码 助力工地实现精细化管理

目录 智慧工地系统介绍 1、可视化大屏 2、视频监控 3、Wi-Fi安全教育 4、环境监测 5、高支模监测 6、深基坑监测 7、智能水电监测 8、塔机升降安全监测 智慧工地系统功能模块 1、基础数据管理 2、考勤管理 3、安全隐患管理 4、视频监控 5、塔吊监控 6、升降机监…

代码随想录算法训练营|day40

第九章 动态规划 343.整数拆分96.不同的二叉搜索树代码随想录文章详解 343.整数拆分 dp[i]表示拆分i得到的最大乘积&#xff0c;对于[1,i)范围内的任意数j&#xff0c;dp[i]最大&#xff0c;即max(j与(i-j)乘积, j与(i-j)最大拆分结果dp[i-j]) 边界情况&#xff1a;对于一个正…