Go 中的生成器并发模式:综合指南
1。运行每个示例:不要只阅读代码。输入它,运行它,然后观察其行为。⚠️ 这个系列如何进行?
2。实验和打破常规: 删除睡眠并看看会发生什么,更改通道缓冲区大小,修改 goroutine 计数。
打破东西会教你它们是如何工作的
3。关于行为的原因: 在运行修改后的代码之前,尝试预测结果。当您看到意外行为时,请停下来思考原因。挑战解释。
4。建立心理模型:每个可视化代表一个概念。尝试为修改后的代码绘制自己的图表。
在上一篇文章中,我们探讨了 goroutine 和通道的基础知识,它们是 Go 并发的构建块。阅读此处:

理解和可视化 Golang 中的 Goroutine 和 Channel
Souvik Kar Mahapatra ・ 12 月 20 日
现在,让我们看看这些原语如何组合起来形成解决现实世界问题的强大模式。
在这篇文章中,我们将介绍生成器模式并尝试将它们可视化。因此,让我们做好准备,因为我们将亲手完成整个过程。
生成器模式
生成器就像一个喷泉,不断产生我们可以在需要时使用的值。
在 Go 中,它是一个生成值流并通过通道发送它们的函数,允许程序的其他部分按需接收这些值。
让我们看一个例子:
// generateNumbers creates a generator that produces numbers from 1 to max func generateNumbers(max int) chan int { // Create a channel to send numbers out := make(chan int) // Launch a goroutine to generate numbers go func() { // Important: Always close the channel when done defer close(out) for i := 1; i <= max; i++ { out <- i // Send number to channel } }() // Return channel immediately return out } // Using the generator func main() { // Create a generator that produces numbers 1-5 numbers := generateNumbers(5) // Receive values from the generator for num := range numbers { fmt.Println("Received:", num) } }
在这个例子中,我们的生成器函数做了三件关键的事情:
- 创建一个通道来发送值
- 启动 goroutine 来生成值
- 立即返回频道供消费者使用
为什么使用生成器?
- 将价值生产与消费分开
- 按需生成值(惰性求值)
- 可以表示无限序列而不消耗无限内存
- 允许并发生产和消费值
现实世界的用例
逐行读取大文件:
func generateLines(filename string) chan string { out := make(chan string) go func() { defer close(out) file, err := os.Open(filename) if err != nil { return } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { out <- scanner.Text() } }() return out }
现在您可能会想,它有什么特别之处?我们可以做同样的事情,比如生成数据序列或在没有 goroutine 的情况下逐行读取。是不是太过分了?让我们尝试可视化这两种情况:
没有 goroutine
// Traditional approach func getNumbers(max int) []int { numbers := make([]int, max) for i := 1; i <= max; i++ { numbers[i-1] = i // Imagine some heavy computation here time.Sleep(100 * time.Millisecond) } return numbers }
这里需要等待一切准备就绪才可以开始处理。
带有 goroutine
// Generator approach func generateNumbers(max int) chan int { out := make(chan int) go func() { defer close(out) for i := 1; i <= max; i++ { out <- i // Same heavy computation time.Sleep(100 * time.Millisecond) } }() return out }
您可以在数据仍在生成时开始处理数据。
生成器模式的主要优点:
非阻塞执行:生成和处理同时发生
内存效率:一次可以生成并处理一个值,无需立即存储在内存中
无限序列:可以生成无限序列而不会出现内存问题
反压处理:如果你的消费者很慢,生成器自然会减慢(由于通道阻塞),防止内存过载。
// generateNumbers creates a generator that produces numbers from 1 to max func generateNumbers(max int) chan int { // Create a channel to send numbers out := make(chan int) // Launch a goroutine to generate numbers go func() { // Important: Always close the channel when done defer close(out) for i := 1; i <= max; i++ { out <- i // Send number to channel } }() // Return channel immediately return out } // Using the generator func main() { // Create a generator that produces numbers 1-5 numbers := generateNumbers(5) // Receive values from the generator for num := range numbers { fmt.Println("Received:", num) } }
常见陷阱和解决方案
- 忘记关闭频道
func generateLines(filename string) chan string { out := make(chan string) go func() { defer close(out) file, err := os.Open(filename) if err != nil { return } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { out <- scanner.Text() } }() return out }
- 不处理错误
// Traditional approach func getNumbers(max int) []int { numbers := make([]int, max) for i := 1; i <= max; i++ { numbers[i-1] = i // Imagine some heavy computation here time.Sleep(100 * time.Millisecond) } return numbers }
- 资源泄漏:将生成器与资源(如文件)一起使用时,请确保正确清理:
// Generator approach func generateNumbers(max int) chan int { out := make(chan int) go func() { defer close(out) for i := 1; i <= max; i++ { out <- i // Same heavy computation time.Sleep(100 * time.Millisecond) } }() return out }
这就是生成器模式的全部内容。接下来是管道并发模式。请继续关注,清除您对 Golang 并发的概念。
我错过了什么吗?有疑问吗?有什么有趣的事可以分享吗?欢迎大家提出意见。
以上是Go 中的生成器并发模式:综合指南的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

OpenSSL,作为广泛应用于安全通信的开源库,提供了加密算法、密钥和证书管理等功能。然而,其历史版本中存在一些已知安全漏洞,其中一些危害极大。本文将重点介绍Debian系统中OpenSSL的常见漏洞及应对措施。DebianOpenSSL已知漏洞:OpenSSL曾出现过多个严重漏洞,例如:心脏出血漏洞(CVE-2014-0160):该漏洞影响OpenSSL1.0.1至1.0.1f以及1.0.2至1.0.2beta版本。攻击者可利用此漏洞未经授权读取服务器上的敏感信息,包括加密密钥等。

在BeegoORM框架下,如何指定模型关联的数据库?许多Beego项目需要同时操作多个数据库。当使用Beego...

后端学习路径:从前端转型到后端的探索之旅作为一名从前端开发转型的后端初学者,你已经有了nodejs的基础,...

GoLand中自定义结构体标签不显示怎么办?在使用GoLand进行Go语言开发时,很多开发者会遇到自定义结构体标签在�...

Go语言中使用RedisStream实现消息队列时类型转换问题在使用Go语言与Redis...

Go语言中用于浮点数运算的库介绍在Go语言(也称为Golang)中,进行浮点数的加减乘除运算时,如何确保精度是�...

Go爬虫Colly中的Queue线程问题探讨在使用Go语言的Colly爬虫库时,开发者常常会遇到关于线程和请求队列的问题。�...

Go语言中字符串打印的区别:使用Println与string()函数的效果差异在Go...
