GO_并发编程---channel

发布时间:2026/9/20 15:59:23

GO_并发编程---channel 前置回顾Go 并发核心设计理念不要通过共享内存来通信而要通过通信来共享内存goroutine之间数据同步、数据交互统一依靠channel实现解决多协程资源竞争问题。一、Channel 基础概念作用实现多个 goroutine 同步协程之间安全共享、传递数据底层理解可以把 channel 看作一根管道 / 水管两端分别对应发送、接收无缓存管道一端没就绪另一端会阻塞有缓存管道缓冲区存数据缓冲区满 / 空时发生阻塞。传递特性channel 本身是地址传递引用类型不是值传递。二、Channel 创建语法使用内置函数make创建分两种go// 1. 无缓冲通道容量为0 ch : make(chan 数据类型) ch : make(chan int, 0) // 2. 有缓冲通道capacity代表缓冲区最大存储数量 ch : make(chan string, 5)三、Channel 收发操作符--是通道专属操作符四种常用写法go// 1. 发送数据把value写入通道 channel - value // 2. 接收数据直接丢弃不保存 -channel // 3. 接收数据赋值给变量x x : -channel // 4. 接收判断通道状态重点 // oktrue通道未关闭正常读到数据 // okfalse通道已关闭无数据可读 x, ok : -channel阻塞规则通道无数据可读时接收操作阻塞无缓冲通道、缓冲区已满的有缓冲通道发送操作阻塞。四、无缓冲 Channel同步通道定义创建时容量为 0缓冲区无法存储任何数据。核心特性发送和接收必须同时就绪否则阻塞先执行发送ch - val阻塞等待其他协程接收先执行接收-ch阻塞等待其他协程发送只有收发双方同时到位数据才会完成传递协程继续向下执行。示例 1利用无缓冲通道实现协程同步gopackage main import fmt // 全局通道 var ch make(chan int) func Printer(str string) { for _, v : range str { fmt.Print(string(v)) } fmt.Println() } func person1() { Printer(hello) ch - 666 // 发送数据通知person1执行完毕 } func person2() { -ch // 阻塞等待收到数据后才执行打印 Printer(world) } func main() { go person1() go person2() for {} // 阻塞主协程防止程序退出 }执行顺序固定hello先打印再打印world实现协程同步。示例 2无缓冲通道完整读写演示gopackage main import ( fmt time ) func main() { // 无缓冲通道 ch : make(chan int, 0) fmt.Printf(len(ch)%d, cap(ch)%d\n, len(ch), cap(ch)) // 子协程发送数据 go func() { for i : 0; i 3; i { fmt.Println(子协程 i , i) ch - i // 无缓冲会阻塞等待主协程读取 } }() time.Sleep(2 * time.Second) // 主协程循环读取 for i : 0; i 3; i { num : -ch fmt.Println(num , num) } }五、有缓冲 Channel异步通道定义创建时指定容量 capacity内部自带缓冲区可以预先存储多条数据。go// 缓冲区最多存3个int ch : make(chan int, 3)核心特性缓冲区未满发送数据不会阻塞直接存入缓冲区缓冲区已满发送操作阻塞等待其他协程读取腾出空间缓冲区有数据接收操作直接读取不阻塞缓冲区为空接收操作阻塞。示例有缓冲通道读写gopackage main import ( fmt time ) func main() { ch : make(chan int, 3) go func() { for i : 0; i 3; i { ch - i fmt.Printf(子协程[%d] len(ch)%d, cap(ch)3\n, i, len(ch)) } }() time.Sleep(2 * time.Second) for i : 0; i 3; i { num : -ch fmt.Println(num , num) } }六、关闭 Channel close ()使用场景确认后续不会再向通道发送数据时调用close(ch)关闭通道。重要规则关闭后的通道禁止发送数据发送会直接 panic 崩溃通道关闭后缓冲区剩余数据仍可正常读取缓冲区数据全部读完后再次读取会返回okfalse。方式 1if 判断 ok 读取通道gopackage main import fmt func main() { ch : make(chan int) go func() { for i : 0; i 5; i { ch - i } close(ch) // 写完数据关闭通道 }() for { num, ok : -ch if ok true { fmt.Println(num , num) } else { fmt.Println(通道已关闭退出循环) break } } }方式 2range 遍历通道推荐for range会自动循环读取通道数据通道关闭后自动结束循环无需手动判断 okgofor num : range ch { fmt.Println(num , num) }七、单向 Channel只读 / 只写通道语法区分箭头方向go// 双向通道可读可写默认 var ch chan int // 只写通道chan-只能发送数据不能读取 var writeCh chan- float64 // 只读通道-chan只能读取数据不能发送 var readCh -chan int转换规则双向通道可以隐式转为单向通道单向通道不能转回双向通道编译报错。gopackage main import fmt func main() { ch : make(chan int) // 双向通道 // 双向转单向合法 var writeCh chan- int ch var readCh -chan int ch writeCh - 666 // 只写通道执行发送 -readCh // 只读通道执行接收 // 错误单向无法转回双向 // var ch2 chan int writeCh }实战场景生产者消费者模型单向通道用于函数参数约束规范函数行为代码可读性更高producer 生产者只写通道负责生产数据写入管道consumer 消费者只读通道负责读取管道数据gopackage main import fmt // 生产者只写通道 func producer(out chan- int) { for i : 0; i 10; i { out - i * i } close(out) // 生产完成关闭通道 } // 消费者只读通道 func consumer(in -chan int) { for num : range in { fmt.Println(num , num) } } func main() { ch : make(chan int) go producer(ch) // 开启生产者协程 consumer(ch) // 主线程消费 }八、Channel 核心复习总结Go 并发核心思想通信共享内存channel 是 goroutine 通信载体channel 是引用类型分无缓冲、有缓冲两类无缓冲通道收发必须成对出现天然实现同步有缓冲通道异步存储数据close()关闭通道后不能发送但剩余数据可读取range 简化通道循环读取单向通道约束读写权限常用于生产者消费者模型阻塞逻辑无数据读阻塞、缓冲区满写阻塞。
延伸阅读

更多相关文章

2026/9/20 15:59:23

AM275x CBASS防火墙配置实战:权限控制与地址范围详解

1. CBASS防火墙核心概念与AM275x安全架构解析在复杂的嵌入式系统,尤其是像TI AM275x这样的高性能信号处理器中,硬件安全不再是“锦上添花”的选项,而是系统稳定运行的基石。我处理过不少因为内存访问越界或权限配置不当导致的系统崩溃、数据泄…

2026/9/20 15:59:23

.NET开发者学习Python:互补优势与实战指南

1. 为什么.NET开发者需要学习Python?作为一名有十年经验的.NET全栈工程师,我最初对Python也是持怀疑态度的——直到我在实际项目中被迫使用它解决了一个C#难以处理的问题。Python在数据科学、机器学习、快速原型开发等领域的生态优势,正在让它…

2026/9/21 10:23:29

STM32软件SPI驱动1.8寸TFT-LCD完整教程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 10:23:29

PCIe 5.0交换芯片如何破解AI集群GPU互联瓶颈

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 10:23:29

2026跨部门协同研发管理系统选型指南:避开踩坑实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 3:28:31

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/21 3:33:19

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/21 0:02:23

OpenResearch:构建可复现的开放式研究工作流

第一次看到“OpenResearch”这个名字,我脑子里冒出的不是某个具体软件,而更像一种研究方式的宣言:开放、可复现、可验证。这三件事放在一起,其实比大多数人想象中难得多。过去几年我一直在折腾自己的研究工作流,从纯纸…

2026/9/20 4:54:47

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/20 5:01:23

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/21 10:29:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码