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

【go从零单排】Closing Channels通道关闭、Range over Channels

挪威特罗姆瑟夜景

🌈Don’t worry , just coding!
内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。

📗概念

在 Go 语言中,通道(channel)的关闭是一个重要的概念,允许发送者通知接收者不再发送任何值。关闭通道可以帮助避免死锁,并使接收者能够知道何时所有数据都已被处理。

💻代码

通道关闭

package main

import "fmt"

func main() {
	jobs := make(chan int, 5) // 创建一个容量为 5 的整型通道 jobs
	done := make(chan bool)   // 创建一个布尔类型的通道 done

	// 启动一个 goroutine 来处理 jobs 通道中的任务
	go func() {
		for {
			//从 jobs 通道接收任务。如果通道关闭且没有更多数据,more 将为 false。
			j, more := <-jobs // 尝试从 jobs 通道接收任务
			if more {         // 如果成功接收任务
				fmt.Println("received job", j)
			} else { // 如果通道已关闭且没有更多的任务
				fmt.Println("received all jobs")
				done <- true // 向 done 通道发送信号,表示所有任务已处理完成
				//主 goroutine 等待 goroutine 完成所有任务处理。当 goroutine 向 done 通道发送信号后,主 goroutine 将继续执行。
				return // 退出 goroutine
			}
		}
	}()

	// 向 jobs 通道发送任务
	for j := 1; j <= 3; j++ {
		jobs <- j
		fmt.Println("sent job", j)
	}
	close(jobs) // 关闭 jobs 通道,表示不再发送更多任务
	fmt.Println("sent all jobs")

	<-done // 等待 goroutine 完成所有任务

	// 尝试从 jobs 通道接收更多任务
	_, ok := <-jobs
	fmt.Println("received more jobs:", ok)
}
//输出
//sent job 1
//sent job 2
//sent job 3
//sent all jobs
//received job 1
//received job 2
//received job 3
//received all jobs
//received more jobs: false

🔍理解

  • go中关闭通道的语法:close(myChannel)
  • 一旦通道被关闭,任何后续的发送操作都会引发panic。
  • 只由发送者关闭通道:通常,只有发送通道的 goroutine 应该关闭通道。接收者不应该关闭通道,因为这可能会导致其他 goroutine 在尝试发送时发生panic。
  • 避免重复关闭:关闭已关闭的通道会导致恐慌,因此在关闭通道之前,确保它未被关闭
  • 使用 range 处理通道:使用 range 迭代通道可以简化关闭通道后的处理逻辑。
  • 从通道返回的第二个值为bool类型,通道开启时为true,通道关闭时为false

💡 Tips小知识点

如何检查通道是否关闭

value, ok := <-myChannel
if !ok {
    fmt.Println("Channel is closed")
}

通道关闭后的情况

package main

import (
	"fmt"
)

func main() {
	jobs := make(chan int)

	// 启动一个 goroutine 来处理 jobs 通道
	go func() {
		for j := range jobs { // 使用 range 迭代接收 jobs 通道的值
			fmt.Println("Processing job:", j)
		}
		fmt.Println("No more jobs, exiting goroutine.")
	}()

	// 发送一些任务
	for i := 1; i <= 5; i++ {
		jobs <- i
		fmt.Println("Sent job:", i)
	}

	close(jobs) // 关闭通道,表示不再发送任务
	fmt.Println("All jobs sent.")

	// 等待 goroutine 完成(在这个简单示例中,它会在接收完所有任务后自动退出)
}
//输出
//Processing job: 1
//Sent job: 1
//Sent job: 2
//Processing job: 2
//Processing job: 3
//Sent job: 3
//Sent job: 4
//Processing job: 4
//Processing job: 5
//Sent job: 5
//All jobs sent.

Range over Channels

使用 range 迭代通道是 Go 语言中处理通道的一种简洁且高效的方式。通过 range 语法,可以自动处理通道的关闭,简化了代码逻辑。

基本用法

package main

import "fmt"

func main() {
	//创建通道queue,buffer为2
	queue := make(chan string, 2)
	queue <- "one" //发送消息到通道
	queue <- "two"
	close(queue) //关闭通道

	for elem := range queue {
		fmt.Println(elem)
	}
}

//输出
//one
//two

使用range处理通道的好处

  • 使用 range 迭代通道时,Go 会持续从通道中接收值,直到通道被关闭为止。
  • 当通道关闭后,range 循环会自动结束,而不会引发panic
  • 在关闭通道后,所有未被读取的值都会被处理完,然后循环自动退出
  • 无需手动检查通道状态:使用 range 可以避免手动检查通道是否关闭或是否还有值,这样可以减少代码的复杂性。
  • 避免死锁风险:在处理通道时,手动检查通道状态可能导致逻辑错误,使用 range 可以有效避免这类问题。

💪无人扶我青云志,我自踏雪至山巅。
在这里插入图片描述


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

相关文章:

  • 【Idea】编译Spring源码 read timeout 问题
  • 密钥轮换时,老数据该如何处理
  • flutter 装饰类【BoxDecoration】
  • 《AI赋能光追:开启图形渲染新时代》
  • [计算机网络]一. 计算机网络概论第一部分
  • Java定时任务不明原因挂掉(定时任务挂掉)以及建议
  • 大模型参数大小,占用多少字节,验证环节需要多少算力;“100B Token,支持8K上下文”是什么意思 ;Llama模型;
  • macOS M2 安装 Jax (jax-metal)
  • 【Linux】查找文件和查找文件匹配内容
  • 034集——JIG效果实现(橡皮筋效果)(CAD—C#二次开发入门)
  • 【清华大学对应镜像】QGIS+Conda+jupyter玩转Python GIS
  • VMnet NAT模式配置
  • NFS-Ganesha 核心架构解读
  • PostgreSQL中如果有Left Join的时候索引怎么加
  • 【Linux】网络编程2
  • 架构师备考-概念背诵(系统架构)
  • LeetCode 热题100之 动态规划1
  • 如何在短时间内备考集成项目管理工程师
  • 一文学习Android中的Treeview
  • FreeRTOS 23:事件组EventGroup创建、删除、置位操作
  • 逆向攻防世界CTF系列27-200simple-check-100
  • 【HarmonyNext】显示提示文字的方法
  • 【大数据学习 | HBASE高级】storeFile文件的合并
  • 【智谱开放平台-注册/登录安全分析报告】
  • 数据中心类DataCenter(二)
  • 【Linux 31】网络层协议 - IP