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

简单易懂,解析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管道&#xff1b;用make初始化管道&#xff1b; len()&#xff1a; 缓冲区中元素个数&#xff0c; cap()&#xff1a; 缓冲区大小 //变量声明 var a chan int //使用make初始化 b : make(chan int) //不带缓冲区 c : make(chan stri…...

STM32 USB 设备的描述信息作用

在使用 STM32 USB 功能时 usbd_desc.c 文件中定义了一段宏&#xff0c;以下解每段宏的用途。 #define USBD_VID 1155 #define USBD_LANGID_STRING 1033 #define USBD_MANUFACTURER_STRING "STMicroelectronics" #define US…...

Redis字符串常见命令(String)

字符串常见命令&#xff08;String&#xff09; Redis 中的字符串类型是一种非常基础且常用的数据类型&#xff0c;它不仅可以存储任何形式的字符串&#xff08;包括文本数据&#xff09;&#xff0c;还可以对数字字符串进行自增、自减等操作。以下是对 Redis 字符串类型常见命…...

Educational Codeforces Round 174 (Rated for Div. 2)(ABCD)

A. Was there an Array? 翻译&#xff1a; 对于整数数组 ​&#xff0c;我们将其相等特征定义为数组 &#xff0c;其中&#xff0c;如果数组 a 的第 i 个元素等于其两个相邻元素&#xff0c;则 &#xff1b;如果数组 a 的第 i 个元素不等于其至少一个相邻元素&#xff0c;则 …...

基于知识图谱的问答系统:后端Python+Flask,数据库Neo4j,前端Vue3(提供源码)

基于知识图谱的问答系统&#xff1a;后端PythonFlask&#xff0c;数据库Neo4j&#xff0c;前端Vue3 引言 随着人工智能技术的不断发展&#xff0c;知识图谱作为一种结构化的知识表示方式&#xff0c;逐渐成为问答系统的重要组成部分。本文将介绍如何构建一个基于知识图谱的问答…...

面试知识点2

文章目录 1. Linux 与 DockerLinux 基本指令VMware 安装 CentOSDocker 拉取镜像创建容器、部署 Spring Boot 项目 2. 关系型数据库 MySQL数据库语法多表关联查询数据库索引 3. 事务与死锁事务的隔离级别死锁的原因和避免方法 4. 排序算法与数据结构二分查找快速排序常见数据结构…...

Django项目之订单管理part1

一.前言 我们前面把django的常用知识点给讲完了&#xff0c;现在我们开始项目部分&#xff0c;项目是一个订单管理系统&#xff0c;我们同时也会在项目之中也会讲一些前面没有用到的知识点。 项目大概流程如下&#xff1a; 核心的功能模块&#xff1a; 认证模块&#xff0c;用…...

基于SSM+Vue的智能汽车租赁平台设计和实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

deepseek本地调用

目录 1.介绍 2.开始调用 2.1模型检验 2.2 通过url调用 3.总结 1.介绍 这篇博客用来教你如何从本地调用ollama中deepseek的模型接口&#xff0c;直接和deepseek进行对话。 2.开始调用 2.1模型检验 首先要保证ollama已经安装到本地&#xff0c;并且已经下载了deepseek模型…...

文件同步工具哪家强?FreeFileSync 免费无限制

FreeFileSync 是一款备受推崇的开源文件同步与备份软件&#xff0c;凭借其卓越的功能和简洁直观的界面&#xff0c;赢得了全球用户的青睐。该软件不仅支持跨平台操作&#xff0c;兼容 Windows、macOS 和 Linux 系统&#xff0c;还能帮助用户在不同设备之间无缝同步文件&#xf…...

捷米特 JM - RTU - TCP 网关应用 F - net 协议转 Modbus TCP 实现电脑控制流量计

一、项目背景 在某工业生产园区的供水系统中&#xff0c;为了精确监测和控制各个生产环节的用水流量&#xff0c;需要对分布在不同区域的多个流量计进行集中管理。这些流量计原本采用 F - net 协议进行数据传输&#xff0c;但园区的监控系统基于 Modbus TCP 协议进行数据交互&…...

Coze扣子怎么使用更强大doubao1.5模型

最近&#xff0c;豆包刚刚发布了最新的doubao1.5系列模型&#xff0c;并且加量不加价。 在性能极大进步的情况下&#xff0c;价格还与之前一致。真是业界良心了。 在同样的价格下&#xff0c;肯定要使用性能更强大的模型嘛 于是我准备把所有的智能体和工作流切换到doubao1.5…...

layui 远程搜索下拉选择组件(多选)

模板使用&#xff08;lay-module/searchSelect&#xff09;&#xff0c;依赖于 jquery、layui.dist 中的 dropdown 模块实现&#xff08;所以data 格式请参照 layui文档&#xff09; <link rel"stylesheet" href"layui-v2.5.6/dist/css/layui.css" /&g…...

嵌入式学习(18)---Linux文件编程中的进程

一、进程的概念 进程:(用来描述 程序动态执行的过程&#xff0c;方便操作系统管理的) 进行中的程序 程序的一次执行过程 (内存 CPU) 程序的实例 程序 ----加载到内存----> 进程 应用场景: 实现并发 同一时刻 同时发生 并行 …...

一.AI大模型开发-初识机器学习

机器学习基本概念 前言 本文主要介绍了深度学习基础&#xff0c;包括机器学习、深度学习的概念&#xff0c;机器学习的两种典型任务分类任务和回归任务&#xff0c;机器学习中的基础名词解释以及模型训练的基本流程等。 一.认识机器学习 1.人工智能和机器学习 人工智能&am…...

RoCE和 TCP的区别

RoCE&#xff08;RDMA over Converged Ethernet&#xff09;和 TCP&#xff08;Transmission Control Protocol&#xff09;都是用于数据传输的协议&#xff0c;但它们在多个方面存在显著区别&#xff0c;以下为你详细介绍&#xff1a; 设计目标 RoCE&#xff1a;主要设计目标…...

勒索病毒攻击:如何应对和恢复

近年来,勒索病毒(Ransomware)已经成为全球信息安全领域最具破坏力的威胁之一。无论是个人用户,还是大中型企业,甚至政府机构,勒索病毒的攻击频率和破坏性日益增加。2020年及2021年,勒索病毒攻击不仅数量激增,且其攻击手法、目标和传播方式也变得更加复杂、精密和具有针…...

解决MySQL错误:You can‘t specify target table ‘xxx‘ for update in FROM clause

目录 错误复现场景原因分析解决方案方法1&#xff1a;使用派生表&#xff08;推荐&#xff09;方法2&#xff1a;改用JOIN操作方法3&#xff1a;使用临时表 总结 在编写MySQL的UPDATE或DELETE语句时&#xff0c;如果子查询中直接引用了要操作的目标表&#xff0c;可能会遇到一个…...

在Linux上安装和使用Docker

在Linux上安装和使用Docker&#xff1a;一步步指南 Docker是一种流行的容器化平台&#xff0c;它可以帮助开发者轻松构建、部署和运行应用程序。在本文中&#xff0c;我们将介绍如何在Linux系统上安装Docker&#xff0c;并提供一些常用的Docker命令和使用说明。 1. 安装Docke…...

【Git】四、标签管理

文章目录 Ⅰ. 理解标签Ⅱ. 创建标签① 轻量级标签② 含附注类标签 Ⅲ. 操作标签 Ⅰ. 理解标签 ​ 标签 tag &#xff0c;可以简单的理解为是 对某次 commit 的一个标识&#xff0c;相当于起了一个别名。例如&#xff0c;在项目发布某个版本的时候&#xff0c;针对最后一次 com…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...