简单易懂,解析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…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
