Go之go与channel组合使用
- package main
- import(
- "fmt"
- )
- func main(){
- fmt.Println("Begin doing something!")
- ch := make(chan int)
- go func(){
- fmt.Println("Doing something…")
- ch <-22
- //close(ch)
- }()
- <-ch //此处将被阻塞,直到ch被关闭 或 有值可以取出
- fmt.Println("Done!")
- }
- package main
- import"fmt"
- func worker(start chan bool, index int){
- <-start // 从start中取出数据后,调用20行的case语句
- fmt.Println("This is Worker:", index)
- }
- func main(){
- start := make(chan bool)
- for i :=1; i <=10; i++{
- go worker(start, i)
- }
- //给start赋值10次,让worker方法执行10次
- for i :=1; i <=10; i++{
- start <-true//给start赋值一次,便执行worker函数一次
- }
- v :=1
- //select 被一直阻塞直到start中数据被取出
- select{ //deadlock we expected
- case<-start:
- fmt.Print(v)
- v++
- }
- }
- select常与for一起使用
- for{
- select{
- case x :=<- somechan:
- // … 使用x进行一些操作
- case y, ok :=<- someOtherchan:
- // … 使用y进行一些操作,
- // 检查ok值判断someOtherchan是否已经关闭
- case outputChan <- z:
- // … z值被成功发送到Channel上时
- default:
- // … 上面case均无法通信时,执行此分支
- }
- }
- 终结woker
- package main
- import(
- "fmt"
- "time"
- )
- func worker(die chan bool, index int){
- fmt.Println("Begin: This is Worker:", index)
- for{
- select{
- //case xx:
- //做事的分支
- case<-die: //到这里就被阻塞,运行main中的close后输出 done
- fmt.Println("Done: This is Worker:", index)
- return
- }
- }
- }
- func main(){
- die:= make(chan bool)
- for i :=1; i <=10; i++{
- go worker(die, i)
- }
- time.Sleep(time.Second*5)
- close(die)
- select{}//deadlock we expected
- }
- 终结验证
- package main
- import(
- "fmt"
- //"time"
- )
- func worker(die chan bool){
- fmt.Println("Begin: This is Worker")
- for{
- select{
- //case xx:
- //做事的分支
- case<-die://这里等待27行的赋值语句,如果没有赋值,一直阻塞
- fmt.Println("Done: This is Worker")
- die<-true
- return
- }
- }
- }
- func main(){
- die:= make(chan bool)
- go worker(die)
- die<-true
- istrue :=<-die//这里等待16行的赋值,赋值完毕后程序继续执行
- fmt.Println("Worker goroutine has been terminated", istrue)
- }
- 关闭的Channel永远不会阻塞
- package main
- import"fmt"
- func main(){
- cb := make(chan bool)
- close(cb)//当cb被关闭后,所有的取值操作将不会被阻塞
- x :=<-cb
- fmt.Printf("%#v\n", x)
- x, ok :=<-cb
- fmt.Printf("%#v %#v\n", x, ok)
- ci := make(chan int)
- close(ci)
- y :=<-ci //即使ci被关闭,照样可以从ci中取数据,取得0
- fmt.Printf("%#v\n", y)
- cb <-true
- }
false
false false
0
panic: send on closed channel
19行将报异常
可以看到在一个已经close的unbuffered channel上执行读操作,回返回channel对应类型的零值,比如bool型channel返回false,int型channel返回0。但向close的channel写则会触发panic。不过无论读写都不会导致阻塞。
- (5)关闭带缓存的channel
- package main
- import"fmt"
- func main(){
- c := make(chan int,3)
- c <-15
- c <-34
- c <-65
- close(c)
- fmt.Printf("%d\n",<-c)//channel被关闭后,照样可以从channel中取出数据,只是不能向其中写数据
- fmt.Printf("%d\n",<-c)
- fmt.Printf("%d\n",<-c)
- fmt.Printf("%d\n",<-c)//当channel中数据全部被取出时,将输出0
- c <-1
- }
- range
- package main
- import"fmt"
- func generator(strings chan string){
- strings <-"Five hour's New York jet lag"
- strings <-"and Cayce Pollard wakes in Camden Town"
- strings <-"to the dire and ever-decreasing circles"
- strings <-"of disrupted circadian rhythm."
- close(strings)
- }
- func main(){
- strings := make(chan string)
- go generator(strings)
- for s := range strings {
- fmt.Printf("%s\n", s)//这里的s 相当于 <- strings,只有赋值之后才能读取到,否则一直阻塞
- }
- fmt.Printf("\n")
- }
package mainimport"fmt"func newUniqueIDService()<-chan string{id := make(chan string)go func(){var counter int64 =0for{id <- fmt.Sprintf("%x", counter)counter +=1}}()return id}func main(){id := newUniqueIDService()for i :=0; i <10; i++{fmt.Println(<-id) //被阻塞,直到id被赋值}}
- 读取时为空
idle := make(chan []byte,5)//用一个带缓冲的channel构造一个简单的队列select{case<-idle://尝试从idle队列中读取fmt.Println("读取")default://队列空,分配一个新的bufferfmt.Println("写入")}
- 写入时已满
package mainimport("fmt")func main(){idle := make(chan []int,10)//用一个带缓冲的channel构造一个简单的队列var b =[]int{2,1}select{case idle <- b://尝试向队列中插入一个bufferfmt.Println(idle)default://队列满?println("队列满")}}
- nil channels阻塞 : 对一个没有初始化的channel进行读写操作都将发生阻塞
package mainfunc main(){var c chan intc <-1}
- 循环输出
package mainimport"fmt"import"time"func main(){var c1, c2 chan int= make(chan int), make(chan int)go func(){time.Sleep(time.Second*5)c1 <-5close(c1)}()go func(){time.Sleep(time.Second*7)c2 <-7close(c2)}()for{select{case x :=<-c1://在等待5s后,把值取出,如果close(c1)那么,将一直输出0fmt.Println(x)case x :=<-c2://在等待7s后,输出c2的值并退出fmt.Println(x)return}}fmt.Println("over")}
package mainimport"fmt"import"time"func main(){var c1, c2 chan int= make(chan int), make(chan int)go func(){time.Sleep(time.Second*5)c1 <-5close(c1)}()go func(){time.Sleep(time.Second*7)c2 <-7close(c2)}()for{select{case x, ok :=<-c1://如果c1未被关闭,则输出x,如果x关闭,c1=nilif!ok {c1 =nil}else{fmt.Println(x)}case x, ok :=<-c2://如果c2未被关闭,则输出x,如果x关闭,c2=nilif!ok {c2 =nil}else{fmt.Println(x)}}if c1 ==nil&& c2 ==nil{break//如果=nil那么推出}}fmt.Println("over")}
- 超时机制Timeout
func worker(start chan bool){timeout := time.After(30* time.Second)for{select{// … do some stuffcase<- timeout:return}}}
- 心跳HeartBeart
func worker(start chan bool){heartbeat := time.Tick(30* time.Second)for{select{// … do some stuffcase<- heartbeat://… do heartbeat stuff}}}
Go之go与channel组合使用的更多相关文章
- 深度解密Go语言之channel
目录 并发模型 并发与并行 什么是 CSP 什么是 channel channel 实现 CSP 为什么要 channel channel 实现原理 数据结构 创建 接收 发送 关闭 channel ...
- nodejs 循环中操作需要同步执行解决方案
最近用nodejs做了个针对某网站的小爬虫.干坏事得低调对吧,不能同时开太多的网络访问,结果各种回调/循环虐的心力交瘁. 经过了n次的百度\哥哥后终于拼出了自己要的功能.不敢独享分享出来以供大家参考. ...
- zz——Recent Advances on Object Detection in MSRA
本文由DataFun社区根据微软亚洲研究院视觉组Lead Researcher Jifeng Dai老师在2018 AI先行者大会中分享的<Recent Advances on Object D ...
- Java中的IO与NIO
前文开了高并发学习的头,文末说了将会选择NIO.RPC相关资料做进一步学习,所以本文开始学习NIO知识. IO知识回顾 在学习NIO前,有必要先回顾一下IO的一些知识. IO中的流 Java程序通过流 ...
- 《Go 语言并发之道》读后感 - 第四章
<Go 语言并发之道>读后感-第四章 约束 约束可以减轻开发者的认知负担以便写出有更小临界区的并发代码.确保某一信息再并发过程中仅能被其中之一的进程进行访问.程序中通常存在两种可能的约束: ...
- flume-拦截器、channel选择器、sink组合sink处理器
1. Flume Interceptors Flume有能力修改/删除流程中的events.这是在拦截器(interceptor)的帮助下完成的.拦截器(Interceptors)是实现org.apa ...
- Channel
提起Channel,JDK的NIO类库的重要组成部分,就是提供了java.nio.SocketChannel和java.nio.ServerSocketChannel,用于非阻塞的I/O操作. 类似于 ...
- Netty那点事: 概述, Netty中的buffer, Channel与Pipeline
Netty那点事(一)概述 Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户ne ...
- Java NIO 之 Socket Channel
在Java NIO中用Channel来对程序与进行I/O操作主体的连接关系进行抽象,这些IO主体包括如文件.Socket或其他设备.简而言之,指代了一种与IO操作对象间的连接关系. 按照Channel ...
随机推荐
- 微信公众平台开发 - 动手篇。使用weinxinFundation开始一个微信公众平台的开发
本文主要讲解如何使用 weinxinFundation 进行二次开发. 步骤如下: 1.创建新的web项目. 在eclipse里新建一个dynamicly web project,比如本文叫weixi ...
- logback.xml配置文件详解
越是老司机越会对日志重视. 如下配置实现了 1.日志文件使用相对路径输出. 2.从日期与文件大小两个纬度分割. 3.特定包与类的日志输出 ** 当存在多个name相同的logger时,逻辑不是很清楚 ...
- https://github.com/cobolfoo/gdx-skineditor
https://github.com/cobolfoo/gdx-skineditor A skin editor for libgdx 0.3
- What Great .NET Developers Ought To Know (More .NET Interview Questions)
A while back, I posted a list of ASP.NET Interview Questions. Conventional wisdom was split, with ab ...
- Qt添加驱动——Qt数据库之添加MySQL驱动插件
Qt数据库之添加MySQL驱动插件(1) 现在可用的数据库驱动只有3种,在Qt中,我们需要自己编译其他数据库驱动的代码,让它们以插件的形式来使用.下面我们就以现在比较流行的MySQL数据库为例,说明一 ...
- 关于Unity中的光照(六)
反射探头 1:镜子金属等具有光滑表面的物体都会反射,而游戏中计算实时反射非常消耗CPU的资源, unity5.0新增了一个反射探头的技术,通过采样点,生成反射Cubemap,然后通过特定的着色器从Cu ...
- 第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS
第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS PhantomJS虚拟浏览器 phantomjs 是一个基于js的webkit内核无头浏览器 ...
- 学习Unity的步骤
作者:王选易链接:https://www.zhihu.com/question/23790314/answer/46815232来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- tophat-fusion 鉴定融合基因
tophat-fusion 是一款利用RNA_seq 数据鉴定融合基因的工具,官网链接如下: http://ccb.jhu.edu/software/tophat/fusion_index.shtml ...
- unity3d Matrix4x4列为主序
unity3d的矩阵一直用,但是之前都是测试着用的,效果虽然正确,但是一直没搞清楚它是行矩阵还是列矩阵 今天测试了下 Matrix4x4 mat4 = Matrix4x4.Perspective(30 ...