简单易懂,解析Go语言中的Channel管道
Channel 管道
1 初始化
可用var声明nil管道;用make初始化管道;
len(): 缓冲区中元素个数, cap(): 缓冲区大小
//变量声明
var a chan int
//使用make初始化
b := make(chan int) //不带缓冲区
c := make(chan string,2) // 带缓冲区
ch1 := make(chan int) // 0 0
ch2 := make(chan int, 2)// 1 2
ch2 <- 1
fmt.Println(len(ch1), len(ch2), cap(ch1), cap(ch2))
2 读写操作
用 " <- "来表示数据流向,缓冲区满时写/缓冲区空时读 都会阻塞,直到被其他携程唤醒
a := make(chan int, 3)
a <- 1 //数据写入管道
<-a //管道读出数据
管道默认双向可读写,但也可在创建函数时显示单向读写
func write(ch chan<- int,a int) {ch <- a// <- ch 无效运算: <- ch (从仅发送类型 chan<- int 接收)
}func read(ch <-chan int) {<- ch//ch <- 1 无效运算: ch <- 1 (发送到仅接收类型 <-chan int)
}
读写值为nil的管道,会永久阻塞,触发死锁
var ch chan intch <- 1 // fatal error: all goroutines are asleep - deadlock!<-ch // fatal error: all goroutines are asleep - deadlock!
读写已关闭管道:有缓冲区成功可读缓冲区内容,无缓冲区读零值并返回false;写已关闭管道会触发panic
关闭后,等待队列中的携程全部唤醒,按照上述规则直接返回
ch1 := make(chan int)
ch2 := make(chan int, 2)
go func() {ch1 <- 1
}()
ch2 <- 2
close(ch1)
close(ch2)
v1, b1 := <-ch1 //0 false
v2, b2 := <-ch2 //2 true
println(v1, v2, b1, b2)
ch1 <- 1 //panic: send on closed channel
ch2 <- 1 //panic: send on closed channel
3 实现原理
简单来说,channel底层是通过环形队列来实现其缓冲区的功能。再加上两个等待队列来存除被堵塞的携程。最后加上互斥锁,保证其并发安全
type hchan struct {
qcount uint // 队列中数据的总数
dataqsiz uint // 环形队列的大小
buf unsafe.Pointer // 指向底层的环形队列
elemsize uint16 // 元素的大小(以字节为单位)
closed uint32 // 表示通道是否已关闭
elemtype *_type // 元素的类型(指向类型信息的指针)
sendx uint // 写入元素的位置
recvx uint // 读取元素的位置
recvq waitq // 等待接收的队列(包含等待接收的 goroutine)
sendq waitq // 等待发送的队列(包含等待发送的 goroutine)// lock 保护 hchan 中的所有字段,以及阻塞在这个通道上的 sudogs 中的几个字段。
// 在持有此锁时,不要更改另一个 G 的状态(特别是不要使 G 变为可运行状态),
// 因为这可能会与栈收缩操作发生死锁。
lock mutex //互斥锁
}
环形队列是依靠数组实现的(buf指向该数组),实现方法类似双指针:一个指向写入位置(sendx),一个指向读取位置(recvx)

等待队列遵循先进先出,阻塞中的携程会被相反的操作依次唤醒
如果写入时,等待接收队列非空(recvq),那么直接将数据给到等待的携程,不用经过缓冲区
select可以监控单/多个管道内是否有数据,有就将其读出;没有也不会阻塞,直接返回;
select执行顺序是随机的
func main() {ch1 := make(chan int)ch2 := make(chan int)go write(ch1)go write(ch2)for {select {case e := <-ch1:fmt.Printf("ch1:%d\n", e)case e := <-ch2:fmt.Printf("ch2:%d\n", e)default:fmt.Println("none")time.Sleep(1 * time.Second)}}
}
func write(ch chan<- int) {for {ch <- 1time.Sleep(time.Second)}
}
for-range 读取管道时,管道关闭之后不会继续读取管道内数据;
for 循环读取管道时,管道关闭后,仍会继续读取管道内的数据,返回一堆 零值,false
func main() {ch1 := make(chan int)go write(ch1)//for e := range ch1 { // 关闭后不会再从管道读取数据// fmt.Print(e)//}//1111for { // 关闭后仍在从管道读取数据。返回 零值,falsefmt.Print(<-ch1)}//11110000000000000000000000000000000000000.....
}
func write(ch chan<- int) {for i := 1; i < 5; i++ {ch <- 1time.Sleep(time.Second)}close(ch)
}
相关文章:
简单易懂,解析Go语言中的Channel管道
Channel 管道 1 初始化 可用var声明nil管道;用make初始化管道; len(): 缓冲区中元素个数, cap(): 缓冲区大小 //变量声明 var a chan int //使用make初始化 b : make(chan int) //不带缓冲区 c : make(chan stri…...
STM32 USB 设备的描述信息作用
在使用 STM32 USB 功能时 usbd_desc.c 文件中定义了一段宏,以下解每段宏的用途。 #define USBD_VID 1155 #define USBD_LANGID_STRING 1033 #define USBD_MANUFACTURER_STRING "STMicroelectronics" #define US…...
Redis字符串常见命令(String)
字符串常见命令(String) Redis 中的字符串类型是一种非常基础且常用的数据类型,它不仅可以存储任何形式的字符串(包括文本数据),还可以对数字字符串进行自增、自减等操作。以下是对 Redis 字符串类型常见命…...
Educational Codeforces Round 174 (Rated for Div. 2)(ABCD)
A. Was there an Array? 翻译: 对于整数数组 ,我们将其相等特征定义为数组 ,其中,如果数组 a 的第 i 个元素等于其两个相邻元素,则 ;如果数组 a 的第 i 个元素不等于其至少一个相邻元素,则 …...
基于知识图谱的问答系统:后端Python+Flask,数据库Neo4j,前端Vue3(提供源码)
基于知识图谱的问答系统:后端PythonFlask,数据库Neo4j,前端Vue3 引言 随着人工智能技术的不断发展,知识图谱作为一种结构化的知识表示方式,逐渐成为问答系统的重要组成部分。本文将介绍如何构建一个基于知识图谱的问答…...
面试知识点2
文章目录 1. Linux 与 DockerLinux 基本指令VMware 安装 CentOSDocker 拉取镜像创建容器、部署 Spring Boot 项目 2. 关系型数据库 MySQL数据库语法多表关联查询数据库索引 3. 事务与死锁事务的隔离级别死锁的原因和避免方法 4. 排序算法与数据结构二分查找快速排序常见数据结构…...
Django项目之订单管理part1
一.前言 我们前面把django的常用知识点给讲完了,现在我们开始项目部分,项目是一个订单管理系统,我们同时也会在项目之中也会讲一些前面没有用到的知识点。 项目大概流程如下: 核心的功能模块: 认证模块,用…...
基于SSM+Vue的智能汽车租赁平台设计和实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
deepseek本地调用
目录 1.介绍 2.开始调用 2.1模型检验 2.2 通过url调用 3.总结 1.介绍 这篇博客用来教你如何从本地调用ollama中deepseek的模型接口,直接和deepseek进行对话。 2.开始调用 2.1模型检验 首先要保证ollama已经安装到本地,并且已经下载了deepseek模型…...
文件同步工具哪家强?FreeFileSync 免费无限制
FreeFileSync 是一款备受推崇的开源文件同步与备份软件,凭借其卓越的功能和简洁直观的界面,赢得了全球用户的青睐。该软件不仅支持跨平台操作,兼容 Windows、macOS 和 Linux 系统,还能帮助用户在不同设备之间无缝同步文件…...
捷米特 JM - RTU - TCP 网关应用 F - net 协议转 Modbus TCP 实现电脑控制流量计
一、项目背景 在某工业生产园区的供水系统中,为了精确监测和控制各个生产环节的用水流量,需要对分布在不同区域的多个流量计进行集中管理。这些流量计原本采用 F - net 协议进行数据传输,但园区的监控系统基于 Modbus TCP 协议进行数据交互&…...
Coze扣子怎么使用更强大doubao1.5模型
最近,豆包刚刚发布了最新的doubao1.5系列模型,并且加量不加价。 在性能极大进步的情况下,价格还与之前一致。真是业界良心了。 在同样的价格下,肯定要使用性能更强大的模型嘛 于是我准备把所有的智能体和工作流切换到doubao1.5…...
layui 远程搜索下拉选择组件(多选)
模板使用(lay-module/searchSelect),依赖于 jquery、layui.dist 中的 dropdown 模块实现(所以data 格式请参照 layui文档) <link rel"stylesheet" href"layui-v2.5.6/dist/css/layui.css" /&g…...
嵌入式学习(18)---Linux文件编程中的进程
一、进程的概念 进程:(用来描述 程序动态执行的过程,方便操作系统管理的) 进行中的程序 程序的一次执行过程 (内存 CPU) 程序的实例 程序 ----加载到内存----> 进程 应用场景: 实现并发 同一时刻 同时发生 并行 …...
一.AI大模型开发-初识机器学习
机器学习基本概念 前言 本文主要介绍了深度学习基础,包括机器学习、深度学习的概念,机器学习的两种典型任务分类任务和回归任务,机器学习中的基础名词解释以及模型训练的基本流程等。 一.认识机器学习 1.人工智能和机器学习 人工智能&am…...
RoCE和 TCP的区别
RoCE(RDMA over Converged Ethernet)和 TCP(Transmission Control Protocol)都是用于数据传输的协议,但它们在多个方面存在显著区别,以下为你详细介绍: 设计目标 RoCE:主要设计目标…...
勒索病毒攻击:如何应对和恢复
近年来,勒索病毒(Ransomware)已经成为全球信息安全领域最具破坏力的威胁之一。无论是个人用户,还是大中型企业,甚至政府机构,勒索病毒的攻击频率和破坏性日益增加。2020年及2021年,勒索病毒攻击不仅数量激增,且其攻击手法、目标和传播方式也变得更加复杂、精密和具有针…...
解决MySQL错误:You can‘t specify target table ‘xxx‘ for update in FROM clause
目录 错误复现场景原因分析解决方案方法1:使用派生表(推荐)方法2:改用JOIN操作方法3:使用临时表 总结 在编写MySQL的UPDATE或DELETE语句时,如果子查询中直接引用了要操作的目标表,可能会遇到一个…...
在Linux上安装和使用Docker
在Linux上安装和使用Docker:一步步指南 Docker是一种流行的容器化平台,它可以帮助开发者轻松构建、部署和运行应用程序。在本文中,我们将介绍如何在Linux系统上安装Docker,并提供一些常用的Docker命令和使用说明。 1. 安装Docke…...
【Git】四、标签管理
文章目录 Ⅰ. 理解标签Ⅱ. 创建标签① 轻量级标签② 含附注类标签 Ⅲ. 操作标签 Ⅰ. 理解标签 标签 tag ,可以简单的理解为是 对某次 commit 的一个标识,相当于起了一个别名。例如,在项目发布某个版本的时候,针对最后一次 com…...
Moonlight Internet Hosting Tool:零配置实现远程游戏串流的终极解决方案
Moonlight Internet Hosting Tool:零配置实现远程游戏串流的终极解决方案 【免费下载链接】Internet-Hosting-Tool Enable Moonlight streaming from your PC over the Internet with no configuration required 项目地址: https://gitcode.com/gh_mirrors/in/Int…...
这才是我们热血沸腾的组合技啊!
臭猪妞更新文章不更,纪念日更得轻快 附:256天创作纪念日 平常会发一些题解,笔记,不太勤快。 我的第一篇文章是《P5736 【深基7.例2】质数筛题解》(当时只会发题解,也才学到了排序) 现在&#…...
变量声明改成文本格式
开题日期:2026.4.28 更新日期:2026.4.28 文章目录一、常规的显示界面二、设置后的显示界面三、设置方法前言 SCL 一、常规的显示界面 二、设置后的显示界面 FUNCTION_BLOCK "块_2"VAR_INPUTEND_VARVAR_OUTPUTEND_VARVAR_IN_OUTEND_VARVAREND_V…...
Keil5编译报错找不到ARM编译器?手把手教你安装AC5.06(附路径配置避坑指南)
Keil5编译报错找不到ARM编译器?手把手教你安装AC5.06(附路径配置避坑指南) 当你满怀期待地打开一个STM32项目准备大展身手时,Keil5突然弹出一个令人窒息的报错:"Target uses ARM-Compiler Default Compiler Versi…...
弦音墨影部署教程:ARM架构服务器(如昇腾)适配Qwen2.5-VL可行性验证
弦音墨影部署教程:ARM架构服务器(如昇腾)适配Qwen2.5-VL可行性验证 1. 项目背景与适配意义 「弦音墨影」是一款将人工智能技术与传统美学深度融合的视频理解系统,其核心基于Qwen2.5-VL多模态大模型。传统部署通常基于x86架构&am…...
free-lunch终极指南:从安装到配置的完整免费软件生态
free-lunch终极指南:从安装到配置的完整免费软件生态 【免费下载链接】free-lunch A curated list of free Windows software, online services and resources. Feel free to contribute! 项目地址: https://gitcode.com/gh_mirrors/fr/free-lunch free-lunc…...
多表关联大平层转JSON树形结构
比如把这种平层数据转化为下面这种树形结构树 [{"id": 2,"parentId": null,"name": "有声书","type": "category","children": [{"id": 1,"parentId": 2,"name": "…...
OpCore Simplify:智能配置黑苹果的终极解决方案
OpCore Simplify:智能配置黑苹果的终极解决方案 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为复杂的OpenCore配置而头疼吗&#x…...
带有1D-1D出瞳扩展和真实光栅的光波导模拟
摘要随着增强与混合现实(AR&MR)领域新应用的发展,导光系统的应用越来越受到人们的关注。为了将光从光源引导到预定的眼箱,采用了分离的1D-1D扩展光瞳的结构,并结合了不同类型的表面刻蚀光栅。因此,在AR/MR器件的设计过程中&am…...
php内核 内网离线编译私有PHP内核完整流程
一套能直接执行的:内网离线编译私有 PHP 内核完整流程,全大白话、偏生产可落地。先一句结论: for shortcuts最佳方式 “联…...
