深入理解 Go Channel:解密并发编程中的通信机制

一、Channel管道
1、Channel说明
  • 共享内存交互数据弊端
    • 单纯地将函数并发执行是没有意义的。函数与函数间需要交互数据才能体现编发执行函数的意义
    • 虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发送静态问题
    • 为了保证数据交换的正确性,必须使用互斥量对内存进行加锁,这种做法势必造成性能问题
  • channel好处
    • Go语言中的通道(channel)是一种特殊的类型
    • 通道像一个传送带或者队列,总是遵循先入先出(First In First Out)原则,保证收发数据的顺序
    • 每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型
    • 如果说goroutine是Go程序并发的执行体,channel就是它们之间的连接
    • channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制
2、channel类型
  • channel是一种类型,一种引用类型
  • 声明管道类型的格式如下
var 变量 chan 元素类型
var ch1 chan int        //声明一个传递整型的管道
var ch2 chan bool        //声明一个传递布尔型的管道
var che chan []int        //声明一个传递int切片的管道
3、创建channel
  • 声明的管道后需要使用make函数初始化之后才能使用
  • 创建channel的格式如下:make(chan 元素类型,容量)
//创建一个能存储10个int类型数据的管道
ch1 := make(chan int,10)
//创建一个能存储4个bool类型数据的管道
ch2 := make(chan bool,4)
//创建一个能存储3个[]int切片类型数据的管道
ch3 := make(chan []int,3)

二、channel操作

  • 管道有发送(send)、接收(receive)和关闭(close)三种操作
  • 发送和接收使用<-符合
  • 现在我们先使用以下语句定义一个管道
ch := make(chan int,3)
1、发送(将数据放在管道内)
  • 将一个值发送到管道中
ch <- 10    //把10发送到ch中
2、接收(从管道内取值)
  • 从一个管道中接收值
x := <- ch    //从ch中接收值并赋值给变量x
<- ch        //从ch中接收值,忽略结果
3、关闭管道
  • 我们通过调用内置的close函数来关闭管道:close(ch)
  • 关于关闭管道需要注意的事情是,只有在通知接收方goroutine所有的数据都发送完毕的时候才需要关闭管道
  • 管道是可以被垃圾回收机制回收的,它和关闭文件是不一样的,在结束操作之后关闭文件是必须要做的,但关闭管道不是必须的
  • 关闭后的管道有以下特点:
    • 对一个关闭的管道再发送值就是导致panic
    • 对一个关闭的管道进行接收会一直获取值直到管道为空
    • 对一个关闭的并且没有值的管道执行接收操作会得到对应类型的零值
    • 关闭一个已经关闭的管道会导致panic
4、管道阻塞
1、无缓冲的管道
  • 如果创建管道的时候没有指定容量,那么我们可以叫这个管道为无缓冲的管道
  • 无缓冲的管道有称为阻塞的管道
package main
import "fmt"func main() {ch := make(chan int)ch <- 10fmt.Println("发送成功")
}
/*
-- 面这段代码能够通过编译,但是执行的时候会出现以下错误
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()E:/_000/Go/Code/demo1.go:6 +0x5f*/

2、有缓冲的管道
  • 解决上面问题的方法还有一种就是使用有缓冲区的管道
  • 我们可以在使用make函数初始化管道的时候为其指定管道的容量
  • 只要管道的容量大于零,那么该管道那么该管道就是有缓冲的管道,管道的容量表示管道中能存放元素的数量。
  • 就像你小区的快递柜只有那么个多格子,格子满了就装不下了,就阻塞了,等到别人取走一个快递员就能往里面放一个。
package main
import "fmt"func main() {ch := make(chan int, 5)ch <- 10ch <- 12fmt.Println("发送成功")
}

三、从 Channel 取值 

1、优雅的从channel取值
  • 当通过通道发送有限的数据时,我们可以通过close函数关闭通道来告知从该通道接收值的goroutine停止等待。
  • 当通道被关闭时,往该通道发送值会引发panic,从该通道里接收的值一直都是类型零值。
  • 那如何判断一个通道是否被关闭了呢?
  • for range的方式判断通道关闭
package mainimport ("fmt"
)func f1(ch1 chan int) {for i := 0; i < 100; i++ {ch1 <- i}close(ch1)
}func f2(ch1 chan int, ch2 chan int) {for {i, ok := <-ch1 // 通道关闭后再取值ok=falseif !ok {break}ch2 <- i * i}close(ch2)
}// channel 练习
func main() {ch1 := make(chan int)ch2 := make(chan int)// 开启goroutine将0~100的数发送到ch1中go f1(ch1)// 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中go f2(ch1, ch2)// 在主goroutine中从ch2中接收值打印for i := range ch2 { // 通道关闭后会退出for range循环fmt.Println(i)}
}
2、Goroutine结合Channel管道
  • 需求 1:定义两个方法,一个方法给管道里面写数据,一个给管道里面读取数据,要求同步进行。
  • 1、开启一个 fn1 的的协程给向管道 inChan 中写入 100 条数据
  • 2、开启一个 fn2 的协程读取 inChan 中写入的数据
  • 3、注意:fn1 和 fn2 同时操作一个管道
  • 4、主线程必须等待操作完成后才可以退出
  • 注:for range的方式判断通道关闭,推出程序
package mainimport ("fmt""sync""time"
)var wg sync.WaitGroup
func main()  {intChan := make(chan int,10)wg.Add(2)go write(intChan)go read(intChan)wg.Wait()fmt.Println("读取完毕...")
}func write(intChan chan int)  {defer wg.Done()for i:=0;i<10;i++{intChan <- i}close(intChan)
}func read(intChan chan int)  {defer wg.Done()for v := range intChan {fmt.Println(v)time.Sleep(time.Second)}
}

四、单向管道

  • 有的时候我们会将管道作为参数在多个任务函数间传递
  • 很多时候我们在不同的任务函数中使用管道都会对其进行限制
  • 比如限制管道在函数中只能发送或只能接收
package main
import ("fmt"
)
func main() {//1. 在默认情况下下,管道是双向//var chan1 chan int //可读可写//2 声明为只写var chan2 chan<- intchan2 = make(chan int, 3)chan2<- 20//num := <-chan2 //errorfmt.Println("chan2=", chan2)//3. 声明为只读var chan3 <-chan intnum2 := <-chan3//chan3<- 30 //errfmt.Println("num2", num2)
}

五、Goroutine池

  • 本质上是生产者消费者模型
  • 在工作中我们通常会使用可以指定启动的goroutine数量–worker pool模式,控制goroutine的数量,防止goroutine泄漏和暴涨。
  • 一个简易的work pool示例代码如下:
package mainimport ("fmt""time"
)func worker(id int, jobs <-chan int, results chan<- int) {for j := range jobs {fmt.Printf("worker:%d start job:%d\n", id, j)time.Sleep(time.Second)fmt.Printf("worker:%d end job:%d\n", id, j)results <- j * 2}
}func main() {jobs := make(chan int, 100)results := make(chan int, 100)// 开启3个goroutinefor w := 1; w <= 3; w++ {go worker(w, jobs, results)}// 5个任务for j := 1; j <= 5; j++ {jobs <- j}close(jobs)// 输出结果for a := 1; a <= 5; a++ {<-results}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows的C盘爆掉了怎么办?

本文参考&#xff1a; C盘太满怎么办&#xff1f;亲测8种好用方法&#xff01; 如果C盘的分区爆掉了&#xff0c;变红色了&#xff0c;是时候该处理这个问题了&#xff0c;解决你的C盘焦虑&#xff01; 第一招&#xff1a;删除C盘文件 首先你会想到清理C盘里面的文件&#x…

数据结构之----数组、链表、列表

数据结构之----数组、链表、列表 什么是数组&#xff1f; 数组是一种线性数据结构&#xff0c;它将相同类型的元素存储在连续的内存空间中。 我们将元素在数组中的位置称为该元素的索引。 数组常用操作 1. 初始化数组 我们可以根据需求选用数组的两种初始化方式&#xff…

机器视觉系统选型-同轴光源分类及应用场景

同轴光源 从与相机同轴的方向均匀照射漫射光 Mark点定位条码识别二维码识别反光物体表面缺陷检测 高亮同轴光源 照射光线与水平方向成低角度夹角Mark点定位反光件表面凹坑、损伤、缺陷印刷电路板二维码识别 平行同轴光源 从与相机同轴方向照射平行度高 的平行光尺寸测量玻璃检…

团队git操作流程

项目的开发要求 项目组厉员每天代码提交不少于20次企业项目开发代码的每天的提交一般提交3-5次代码仓库的管理 git的基础操作流程 命令模式 git push插件模式 vscode git graphGUI软件管理模式 sourcetree git在项目团队化开发中的应用 master(一般是不动的)dev (主要是拿…

2. 如何通过公网IP端口映射访问到设备的vmware虚拟机的ubuntu服务器

文章目录 1. 主机设备是Windows 11系统2. 安装vmware虚拟机3. 创建ubuntu虚拟机&#xff08;据说CentOS 7 明年就不维护了&#xff0c;就不用这个版本的linux了&#xff09;4. 安装nginx服务:默认端口805. 安装ssh服务:默认端口226. 设置主机 -> ubuntu的端口映射7. 设置路由…

【Amis Low Code 结合FastAPI进行前端框架开发】

官方文档 封装思想 直接复制官网json数据即可开发每个json中的接口由fastapi 转发&#xff08;透传&#xff09;使其开发模式与前端思维一致 基础组件 from amis import Page, Service, App from pydantic import BaseModel, Field from fastapi import FastAPI, Request, …

c++学习之智能指针

前言&#xff1a;在此之前我们已经学习到了异常的使用&#xff0c;虽然异常在大部分情况都还可以&#xff0c;但也存在太多缺陷&#xff0c;对于异常的问题&#xff0c;入内存泄漏&#xff0c;在复杂的场景下使用起来也是非常麻烦。为了更好的解决这些问题&#xff0c;c11中引入…

C语言—每日选择题—Day45

第一题 1. 以下选项中&#xff0c;对基本类型相同的指针变量不能进行运算的运算符是&#xff08;&#xff09; A&#xff1a; B&#xff1a;- C&#xff1a; D&#xff1a; 答案及解析 A A&#xff1a;错误&#xff0c;指针不可以相加&#xff0c;因为指针相加可能发生越界&…

【华为数据之道学习笔记】4-2信息架构原则:建立企业层面的共同行为准则

信息架构承载了企业如何管理数据资产的方法&#xff0c;需要从整个企业 层面制订统一的原则&#xff0c;这些原则不仅是对数据专业人员的要求&#xff0c;也是对业务的要求&#xff0c;因为业务才是真正的数据Owner。所以&#xff0c;公司所有业务部门都应该共同遵从信息架构原…

Redis安装教程

文章目录 Redis安装说明1.单机安装Redis1.1.安装Redis依赖1.2.上传安装包并解压1.3.启动1.3.1.默认启动1.3.2.指定配置启动1.3.3.开机自启 2.Redis客户端2.1.Redis命令行客户端2.2.图形化桌面客户端2.2.1.安装2.2.2.建立连接 Redis安装说明 大多数企业都是基于Linux服务器来部…

LeetCode(58)随机链表的复制【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 随机链表的复制 1.题目 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节…

kafka常见问题处理

1. 如何防⽌消息丢失 在生产者层面&#xff0c;我们有个ack参数确认机制 设置成-1&#xff0c;也就是副本全部同步了leader才发送ack&#xff0c;这样确保leader和副本挂掉只剩一个还能 保证消息不丢失 消费者&#xff1a; 把⾃动提交改成⼿动提交 2. 如何防⽌重复消费 在…

Orange Comet利用Sui Kiosk进行游戏道具和知识产权保护

Orange Comet与AMC合作开发基于《行尸走肉》系列的NFT和游戏&#xff0c;首要关注的问题就是保护AMC的知识产权。利用Sui的Kiosk原语不仅让Orange Comet向AMC保证其资产安全&#xff0c;而且为即将推出的《行尸走肉大陆》游戏打开了无限的可能性。 Kiosk是Sui上的一个原语&…

记录一次chatGPT人机协同实战辅助科研——根据词库自动进行情感分析

有一个Excel中的一列&#xff0c;读取文本判断文本包含积极情感词.txt和消极情感词.txt的个数&#xff0c;分别生成两列统计数据 请将 ‘your_file.xlsx’ 替换为你的Excel文件名&#xff0c;Your Text Column’替换为包含文本的列名。 这个程序首先读取了积极和消极情感词&…

mac 环境下 goframe安装GF开发工具 gf-cli(安装包方式安装)

mac 环境下 goframe安装GF开发工具 gf-cli&#xff08;安装包方式安装&#xff09; 安装包网址 链接: link 终端输入命令进行安装 ./gf_darwin_amd64 但是产生如下报错&#xff0c;无法安装 使用一下命令给安装权限 chmod 0777 gf_darwin_amd64 && ./gf_darwin_a…

SAP ABAP excel文件模板上传下载

一&#xff1a;事物码smw0 二&#xff1a;上传步骤 程序源码&#xff1a; l_filename XX.xls.l_muban z123. *&---下载模板PERFORM frm_get_fullpath CHANGING gv_fullpath gv_path gv_name. *&---路径为空则退出IF gv_fullpath IS INITIAL.MESSAGE 用户取消操作 T…

鸿蒙开发 - ohpm安装第三方库

前端开发难免使用第三方库&#xff0c;鸿蒙亦是如此&#xff0c;在使用 DevEco Studio 开发工具时&#xff0c;如何引入第三方库呢&#xff1f;操作步骤如下&#xff0c;假设你使用的是MacOS&#xff0c;假设你已经创建了了一个项目&#xff1a; 一、配置 HTTP Proxy 在打开了…

实时云渲染技术下的虚拟汽车展厅 为什么越来越受青睐?

虚拟汽车展厅正成为各大车企展示和推广汽车的热门选择。这一趋势背后&#xff0c;反映了汽车行业对数字化转型和消费者需求变化的灵敏应对。 虚拟汽车展厅通常需要大量的3D建模和渲染技术来展示汽车的逼真效果。而点量实时云渲染技术可以通过云端计算来实现实时渲染&#xff0…

​hashlib --- 安全哈希与消息摘要​

源码&#xff1a; Lib/hashlib.py 本模块针对许多不同的安全哈希和消息摘要算法实现了一个通用接口。 包括了 FIPS 安全哈希算法 SHA1, SHA224, SHA256, SHA384, SHA512, (定义见 the FIPS 180-4 standard), SHA-3 系列 (定义见 the FIPS 202 standard) 以及 RSA 的 MD5 算法 (…

如何通过上下滑动实现亮度和音量调节(ArkUI)

场景说明 在音视频应用中通常可以通过上下滑动来调节屏幕亮度和音量大小&#xff0c;本例即为大家介绍如何实现上述UI效果。 说明&#xff1a; 由于当前亮度和音量调节功能仅对系统应用开发&#xff0c;所以本例仅讲解UI效果的实现。 效果呈现 本例效果如下&#xff1a; 当在…