Go学习笔记—Channel通道

Go并发通信——Channel

​ Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信。(DO NOT COMMUNICATE BY SHARING MEMORY; INSTEAD, SHARE MEMORY BY COMMUNICATING.)

​ 如果说goroutine是Go程序并发的执行体,channel就是它们之间的连接。channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制。

​ Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。

通道Channel

声明var 变量 chan 元素类型 | make(chan 元素类型, [缓冲大小]) —为引用类型声明内存地址
1. channel—注意点
  1. 向缓冲区已满的通道写入数据会导致goroutine阻塞
  2. 通道中没有数据,读取该通道会导致阻塞(阻塞即goroutine等待,等到缓冲区不满/有数据继续运行,如果主线程main进入等待,则会直接报死锁错误)
  3. 读取已关闭的通道不会引发阻塞,而是返回通道元素类型的零值
  4. 向已关闭的通道写数据会导致panic,重复关闭通道也会引发panic
2. channel—基础操作
ch <- 10      //10存入通道
x := <- ch     //通道中取出第一个值赋给x
<- ch        //取出值,忽略结果
close(ch)     //关闭通道( 通道会被垃圾回收机制回收,不一定非要关闭 )
//**************************************************************************************
select{    //类似于switch,哪个条件满足就会执行哪个,多个满足则随机执行一个,没有满足则阻塞等待case <-ch1:...case data := <-ch2:...case ch3<-data:...default:默认操作
}//select实现通知退出机制
func dosth(done chan struct{}) chan int {ch := make(chan int)go func() {Label:for {select {case ch <- rand.Int():case <-done:		接收到done信号停止运行break Label}}close(ch)}()return ch
}
func main() {done := make(chan struct{})ch := dosth(done)fmt.Println(<-ch)fmt.Println(<-ch)done <- struct{}{}fmt.Println(<-ch)
}//**************************************************************************************
for v := range in {         //for range 进行通道读取,只有当in关闭时,才会终止循环out <- v + 1
}
close(out)
3. channel—无缓冲通道 VS 有缓冲通道

(1)无缓冲通道

无缓冲通道ch := make(chan int)
//对于无缓冲通道,必须有进程在等待接收参数,才可以向通道中传入参数。比如下面的方法,如果把a()的执行放在ch<-10后面,就会引发死锁错误。
func a(ch chan int) {fmt.Printf("我是a,接收到了数字:%d\n", <-ch)
}func main() {ch := make(chan int)go a(ch)ch <- 10fmt.Print("over")}//可以用来实现goroutine同步
func main() {ch := make(chan struct{})go func(){time.Sleep(3*time.second)ch<-struct{}}()<-chfmt.Print("over")
}

(2)有缓冲通道

有缓冲通道make(chan int, 1) //创建一个容量为1的有缓冲区通道
获取通道元素数量len(channel)
获取通道容量cap(channel)

(3)单向通道(在赋值或者传参时,我们将其设为单向通道,使得该函数只能对其进行读/写一个操作)

func squarer(out chan<- int, in <-chan int) {for i := range in {out <- i * i}close(out)
}
4. channel—用例

(1)实现管道

//一个函数的输入参数和输出参数是相同的chan类型,则函数可以调用自己,形成一个调用链
func chain(in chan int) chan int { //作用是将输入的通道值加一out := make(chan int)go func() {for v := range in { //由于in,out声明的都是无缓冲,所以每读一个都会阻塞,等下一个参数out <- v + 1}close(out)}()return out
}func Guandao() {in := make(chan int)go func() {for i := 0; i < 10; i++ { //初始化输入参数in <- i}close(in)}()out := chain(chain(chain(in))) //叠加形成管道for v := range out {           //从最终的输出通道读出结果fmt.Println(v)}
}

(2)实现每个事务一个goroutine

//通过设置任务通道,每当有新任务来临时,为其分配相应的goroutine进行执行
type task struct {num int
}func (t *task) job(wait sync.WaitGroup) {fmt.Println("i am", t.num, "WORKING")time.Sleep(3 * time.Second) //模拟工作流程fmt.Println("i am", t.num, "DONE")wait.Done() //工作完成,wait-1
}func AllocateJob() {wait := sync.WaitGroup{}         //wait防止程序未执行完成就退出taskchan := make(chan *task, 10) //接收任务通道go func() {for i := 1; i <= 10; i++ { //模拟有新工作加入,1秒加入一个task := &task{num: i}wait.Add(1) //wait+1time.Sleep(1 * time.Second)taskchan <- task //任务加入任务通道}}()go func() {for task := range taskchan { //从通道中取出任务,并分配goroutine执行go task.job(wait)}}()wait.Wait()
}

(3)实现future模式

​ 适用于一个流程中需要调用多个子调用的情况,并且这些子调用之间没有依赖。future模式的优势就是将其同步调用转化为异步调用。

//通过通道,实现在执行一个较为耗时的任务时,先通过goroutine调用该任务,由chan传入参数后,并行做其他的事,最后再通过通道获取其运行的结果。
type query struct {in chan stringout chan string
}func doquery(q query) {in := <-q.intime.Sleep(5 * time.Second) //模拟访问数据库进行查询q.out <- in + "的结果"}func Futuretest() {temp := query{in: make(chan string), out: make(chan string)}go doquery(temp)temp.in <- "select * from user"time.Sleep(3 * time.Second) //模拟在进行数据库查询时,我们可以做一些其他的事情fmt.Println(<-temp.out) //做完其他的事情,并且数据库查询也完成了,我们从通道中获取查询结果
}

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

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

相关文章

【转载】程序员技术练级攻略

月光博客6月12日发表了《写给新手程序员的一封信》&#xff0c;翻译自《An open letter to those who want to start programming》&#xff0c;我的朋友&#xff08;他在本站的id是Mailper&#xff09;告诉我&#xff0c;他希望在酷壳上看到一篇更具操作性的文章。因为他也是喜…

FileSystemObject (FSO)对象方法总结及应用

FileSystemObject (FSO)组件可以用来处理系统驱动器&#xff0c;文件夹&#xff0c;和文件。因为它是一个ActiveX控件&#xff0c;所以它能被js&#xff0c;vbs等文件使用&#xff0c;以实现对机器文件系统的操作。 下面将总结一下FSO中的对象和方法&#xff0c;其实FSO中大多数…

IBM如何拥抱Spark

Spark是目前相当火热的开源计算框架&#xff0c;相对于Hadoop&#xff0c;Spark优势是高性能和易用性。Spark的高性能源于其采用内存储存数据&#xff0c;应用可以以内存的速度进行运算&#xff1b;Spark的易用性在于通用的API&#xff0c;用户可以编写复杂的并行计算程序&…

SQL语句导入导出大全

SQL语句导入导出大全/******* 导出到excelEXEC master..xp_cmdshell ’bcp SettleDB.dbo.shanghu out c:\temp1.xls -c -q -S"GNETDATA/GNETDATA" -U"sa" -P""’ /*********** 导入ExcelSELECT * FROM OpenDataSource( ’Microsoft.Jet.OLEDB…

arcgis js 4.x 地图中加入图片

arcgis js 4.x版本&#xff0c;如何加入图片问题&#xff1a;如何将自定义图片放入到arcgis的图层当中&#xff1f;本人在网上查找的方法中&#xff0c;发现大部分方法只适用于3.x版本&#xff0c;只有一种引入自定义BaseDynamicLayer的方法可用&#xff0c;然而按照这种方式&a…

对你的的应用程序进行Debug

对你的的应用程序进行Debug 介绍如何使用Microsoft Visual Studio Code Name "Orcas" Beta 1对基于Silverlight的应用程序进行debugging .在Silverlight中debugging所使用的工具和技巧和其它的 Visual Studio projects是类似的. 想查看更多的关于debugging信息的, 查…

如果reporting server出现“无法安装打印控件”的处理方法。

1.打开"控制面板",选择"添加或删除程序"2.将显示更新更新打勾.3.查找文件"KB956391安装更新"4.卸载此文件即可打印了 转载于:https://www.cnblogs.com/miaomiaoga/archive/2008/12/02/1346319.html

在.Net如何制作自定义的快捷方式(转)

我们用.Net安装程序生成的快捷方式是这样的&#xff0c;如下图&#xff1a;该图中目标所对应的文本框是灰色的&#xff0c;并且下方的查找目标和更改图标两个按钮也是不可用。这样我们根本就没有办法更改这个快捷方式。假如这时有个客户需要在程序启动的时候传入一些参数&#…

大数据——Kafka学习笔记

具体代码可以参考&#xff1a; https://github.com/Ostrich5yw/java4BigData/tree/master/java4Kafka

ITOO高校云平台V3.1--项目总结(一)

高校云平台&#xff0c;可以说是我参加的的一个实战性的项目&#xff0c;刚开始接触&#xff0c;可以说是有点蒙&#xff0c;到真正的用到实践中去的时候才发现&#xff0c;之前学到的好多的知识&#xff0c;还只是依然处于学过的层次上&#xff0c;想要真正的运用到项目中去&a…

TABCTL32.OCX 文件

引用&#xff1a;http://zhidao.baidu.com/question/287980070.html 从网上下载TABCTL32.OCX解压缩后拷贝此文件到c:\windows\system32 点开始 运行 输入 regsvr32 TABCTL32.OCX 显示成功后就可以了。 地址&#xff1a; http://ishare.iask.sina.com.cn/f/7602536.html?fromli…

ASP.Net中控件的EnableViewState属性

在ASP.Net中对各个WebForm控件引入以前没有的EnableViewState属性。这个属性究竟有什么用。我们知道对于WebForm而言&#xff0c;其代码是在服务器端的&#xff0c;以处理客户端的请求。当用户通过浏览器浏览网页的时候&#xff0c;会对网页进行某些操作&#xff0c;比如打开新…

大数据——SparkCore学习笔记

Spark 一、Spark简介 Spark 是一种由 Scala 语言开发的快速、通用、可扩展的大数据分析引擎Spark Core 中提供了 Spark 最基础与最核心的功能Spark SQL 是 Spark 用来操作结构化数据的组件。通过 Spark SQL&#xff0c;用户可以使用 SQL 或者 Apache Hive 版本的 SQL 方言&am…

如何用Mybatis分库分表

分库 在分库的时候 有时候为了方便 一些表需要存放所有库的信息&#xff0c;称为全局库。如&#xff1a;用户表存放所有的用户。 此时分库的思路 数据库分为全局库和业务库&#xff0c;其中业务库又分为N多个库&#xff0c;全局库只放个别表方便开发。 这个时候 就需要一个全局…

Kubernetes权威指南精彩段落

2019独角兽企业重金招聘Python工程师标准>>> 看到上述两段代码&#xff0c;你可能会有一种“开门复动竹, 疑是故人来”的感觉。的确&#xff0c;这段代码经笔者反复考证后认定&#xff1a;100%高仿kubernetes Controller Server中的代码。连传说中的谷歌大神也能cop…

常用文献管理软件使用经验

常用的文献管理软件有&#xff1a;Endnote、Biblioscape和Reference Manager。由于不知道哪个好用&#xff0c;我把三个都装上进行了对比。 一、首先是在Word中引用文献功能的比较。 Endnote是最方便的&#xff0c;工具条上的按键就可以把文献插入到Word中。Biblioscape也能与W…

IMP出现的ORA-01401错误可能和字符集有关(转载)

今天在论坛上&#xff0c;看到有一位朋友问 “我备份数据库后在其他的机器上再导入这个数据库&#xff0c;出现如下错误&#xff0c;并只能导 入部分数据。 IMP-00019: row rejected due to ORACLE error 1401 IMP-00003: ORACLE error 1401 encountered ORA-01401: inserted v…

QT中的pro文件

动态库pro设置VERSION 1.0.1901.0时&#xff0c;产生目标名字总会带数字1解决方法&#xff1a;CONFIG skip_target_version_ext设置输出路径 DESTDIR ./output静态链接 LIBS -L$$PWD/../../lib -lopencv_world320转载于:https://www.cnblogs.com/huanyinglvtuan/p/11280013…

大数据——SparkSQL学习笔记

Spark 一、SparkSQL简介 ​ Spark用来处理结构化数据的一个模块&#xff0c;它提供了两个编程抽象分别叫做DataFrame和DataSet&#xff0c;它们用于作为分布式SQL查询引擎&#xff08;类似于Hive&#xff0c;为便于进行MapReduce操作而使用类SQL语句进行Spark操作&#xff09…

windows phone7资料整理

wp7资料库 http://msdn.microsoft.com/zh-cn/magazine/gg598932.aspx 开发指导视频&#xff1a; http://channel9.msdn.com/Series/Windows-Phone-7-Development-for-Absolute-Beginners 指导博客&#xff1a; http://www.jeffblankenburg.com/2010/09/30/31-days-of-windows-p…