第七章:并发编程 2.Channels --Go 语言轻松入门

embedded/2024/12/3 6:00:31/

Go语言中的通道(Channel)是一种特殊的类型,用于在不同的goroutine之间传递数据和同步执行。通道提供了一种安全的方式来避免数据竞争,并且简化了并发编程的复杂性。下面是关于Go Channels的一些关键点:

1. 基本概念

  • 定义var ch chan int 定义了一个整数类型的通道。
  • 创建:使用 make 函数创建通道,例如 ch := make(chan int) 或者 ch := make(chan int, 10) 创建一个带缓冲的通道。
  • 方向性:可以定义单向通道,如 chan<- int 只能发送,<-chan int 只能接收。
package mainimport ("fmt""time"
)// 定义一个只发送整数的函数
func sendNumbers(ch chan<- int) {for i := 0; i < 5; i++ {fmt.Printf("Sending: %d\n", i)ch <- itime.Sleep(1 * time.Second)}close(ch) // 发送完成后关闭通道
}// 定义一个只接收整数并处理的函数
func processNumbers(ch <-chan int) {for v := range ch {fmt.Printf("Processing: %d\n", v)time.Sleep(1 * time.Second)}
}func main() {// 创建一个无缓冲的整型通道ch := make(chan int)// 启动发送者goroutinego sendNumbers(ch)// 启动处理者goroutinego processNumbers(ch)// 等待一段时间让所有goroutines完成time.Sleep(10 * time.Second)fmt.Println("All messages processed, exiting.")
}

在这里插入图片描述

2. 操作

  • 发送ch <- value 将值发送到通道中。
  • 接收value := <- ch 从通道中接收值。
  • 多值接收value, ok := <- ch 接收值的同时检查通道是否关闭 (okfalse 表示通道已关闭)。

3. 阻塞与非阻塞

  • 无缓冲通道:发送和接收操作会一直阻塞,直到另一方准备好。
package mainimport ("fmt"
)func main() {// 创建一个无缓冲的整型通道ch := make(chan int)// 启动一个发送者goroutinego func() {for i := 0; i < 5; i++ {fmt.Printf("Sender: Sending %d\n", i)ch <- i // 将i发送到通道ch// time.Sleep(1 * time.Second) // 模拟耗时操作}close(ch) // 发送完成后关闭通道}()// 主goroutine作为接收者for v := range ch {fmt.Printf("Receiver: Received %d\n", v)}fmt.Println("All messages received, exiting.")
}

在这里插入图片描述

  • 有缓冲通道:只有当缓冲区满时发送才会阻塞;只有当缓冲区为空时接收才会阻塞。
package mainimport ("fmt"
)func main() {// 创建一个带有缓冲区大小为2的整型通道ch := make(chan int, 2)// 启动一个发送者goroutinego func() {for i := 0; i < 10; i++ {fmt.Printf("Sender: Sending %d\n", i)ch <- i // 将i发送到通道ch// time.Sleep(1 * time.Second) // 模拟耗时操作}close(ch) // 发送完成后关闭通道}()// 主goroutine作为接收者for v := range ch {fmt.Printf("Receiver: Received %d\n", v)}fmt.Println("All messages received, exiting.")
}

在这里插入图片描述

4. 关闭通道

  • 使用 close(ch) 关闭通道。关闭后的通道不能再发送数据,但可以继续接收剩余的数据直到通道为空。

5. 选择器

  • select 语句允许在多个通信操作中进行选择,类似于 switch 语句,但是只处理通信操作。
  • default 子句可以让 select 在没有可用的case时执行。
package mainimport ("fmt""time"
)// main 是程序的入口点。
func main() {// 创建一个无缓冲的channel,用于接收异步操作的结果。ch := make(chan int)// 启动一个goroutine,在后台执行操作。go func() {// 模拟一些耗时操作,比如等待I/O完成。time.Sleep(3 * time.Second)// 将结果发送到channel。ch <- 42}()// 2秒后超时,生成一个超时信号。timeout := time.After(2 * time.Second)// 无限循环,等待结果或超时。for {select {// 当channel接收到值时。case value := <-ch:// 打印接收到的值并退出程序。fmt.Println("Received:", value)return// 当超时信号触发时。case <-timeout:// 打印超时信息并退出程序。fmt.Println("Timed out")return// 默认情况,即没有接收到值也没有超时。default:// 打印等待信息,并短暂暂停以避免忙等待。fmt.Println("Still waiting...")time.Sleep(500 * time.Millisecond)}}
}

在这里插入图片描述

6. 范围循环

  • for range 循环可以用来遍历通道中的数据,直到通道被关闭并且所有数据都被读取。

7. 应用场景

  • 并行计算:通过通道收集结果。
  • 事件分发:作为事件处理器之间的消息队列。
  • 资源池:管理一组可重用资源。

8. 注意事项

  • 不要对同一个通道同时进行多次接收或发送操作。
package mainimport ("fmt"
)// main 是程序的入口点
func main() {// 创建一个带有缓冲区的整型通道ch := make(chan int, 5) // 缓冲区大小为5// 启动两个发送者goroutinego func() {for i := 0; i < 5; i++ {fmt.Printf("Sender 1: Sending %d\n", i)ch <- i}}()go func() {for i := 10; i < 15; i++ {fmt.Printf("Sender 2: Sending %d\n", i)ch <- i}}()// 接收者goroutinefor i := 0; i < 10; i++ {fmt.Printf("Receiver: Received %d\n", <-ch)}
}

在这里插入图片描述

  • 当通道不再使用时应该关闭它,以便接收方能够检测到通道关闭。
  • 使用 range 迭代通道时确保最终会关闭通道,否则会导致死锁。

通过理解和运用这些概念,你可以利用Go的通道来构建高效、可靠的并发程序。


http://www.ppmy.cn/embedded/142525.html

相关文章

渗透测试之Web基础之Linux病毒编写——泷羽sec

声明&#xff1a; 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章。本文只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频 (bilibili.com)https://space.bilibili.com/350329294 导读&#xff1a; 时刻…

工具学习_AVClass

1. AVClass 简介 AVClass是一个Python工具包和命令行工具&#xff0c;旨在自动化地为恶意软件样本打标签和分类。通过输入大量恶意软件样本的AV引擎标签&#xff08;例如&#xff0c;VirusTotal JSON报告&#xff09;&#xff0c;AVClass能够提取并输出每个样本的相关标签。这…

frp软件实现网络穿透

1. 名词 1.1. 网络穿透 网络穿透是一种技术&#xff0c;用于解决内网设备或服务无法直接被外部网络访问的问题。通常&#xff0c;内网设备位于路由器后面&#xff0c;并没有公网 IP 地址&#xff0c;因此外部用户不能直接连接到这些设备。网络穿透通过一些特定的技术手段&…

Jenkins Nginx Vue项目自动化部署

目录 一、环境准备 1.1 Jenkins搭建 1.2 NVM和Nodejs安装 1.3 Nginx安装 二、Jenkins配置 2.1 相关插件安装 2.2 全局工具安装 2.3 环境变量配置 2.4 邮箱配置&#xff08;构建后发送邮件&#xff09; 2.5 任务配置 三、Nginx配置 3.1 配置路由转发 四、部署项目 …

从零开始使用GOT-OCR2.0——多模态OCR项目:微调数据集构建 + 训练(解决训练报错,成功实验微调训练)

在上一篇文章记录了GOT-OCR项目的环境配置和基于官方模型参数的基础使用。环境安装的博文快速链接&#xff1a; 从零开始使用GOT-OCR2.0——多模态通用型OCR&#xff08;非常具有潜力的开源OCR项目&#xff09;&#xff1a;项目环境安装配置 测试使用-CSDN博客 本章在环境配置…

C 语言学习的经典书籍有哪些?

学习C语言的理由 C语言是一种程席设计语言&#xff0c;它是由美国AT&T公司贝尔实验室的Dennis Ritchie于1972年发明的。C语言之所以流行&#xff0c;是因为它简单易用。学习C语言的几个理由如下&#xff1a; (1)C、C#和Java使用一种被称为面向对象程序设计(0bject-Orient…

java的Webclient对象怎解解析400状态码

在Java中使用WebClient处理400状态码&#xff0c;可以通过检查响应状态并根据状态码进行相应的错误处理。以下是几种处理400状态码的方法&#xff1a; 使用onStatus方法判断和处理错误&#xff1a; 你可以使用WebClient的retrieve()方法链中的onStatus方法来检查响应状态码。如…

UE5 MakeSlateBrush 节点的作用

在 Unreal Engine 5 (UE5) 中&#xff0c;MakeSlateBrush 节点是用于 创建或设置一个 Slate Brush 的节点。Slate 是 Unreal Engine 中的 UI 框架&#xff0c;用于构建编辑器界面以及游戏中的用户界面&#xff08;UI&#xff09;。Slate Brush 是 Slate UI 中的一种资源类型&am…