您现在的位置是:首页 > 网络趣梗网络趣梗
channel的中文意思(channel的例句)
2022-09-04 21:58:17网络趣梗0人已围观
简介 channel的中文意思(channel的例句),新营销网红网本栏目通过数据整理汇集了channel的中文意思(channel的例句)相关信息,下面一起看看
channel的中文意思(channel的例句),新营销网红网本栏目通过数据整理汇集了channel的中文意思(channel的例句)相关信息,下面一起看看。
本文总结了11种常见的渠道操作。从更高的角度看渠道,会让你对渠道有更全面的了解。
在介绍11种操作之前,先简单介绍一下通道的使用场景、基本操作和注意事项。
通道的使用场景使用数据流动的通道:
邮件传递,邮件过滤
信号广播
事件和广播
请求和响应转发
任务分配
结果摘要
并发控制
同步和异步
…
通道的基本操作和注意事项通道有三种状态:
Nil,未初始化状态,仅声明,或手动赋值为nil。
活动、正常通道、可读或可写。
关了,关了,关了通道之后不要误认为是nil。
通道可以执行三种操作:
阅读
写
关闭
这三种操作和三种通道状态可以组合成九种情况:
恐慌行动频道正常。通道ch成功阻塞或读取为零。ch-阻塞成功或阻塞死机关闭(ch)死机成功。
对于零通道的情况,不完全遵循上表。有一个特殊的场景:当nil通道处于select的情况下,这个情况会阻塞,但不会造成死锁。
请参考代码:https://dave.cheney.net/2014/03/19/channel-axioms.
以下是使用频道的10种常见操作。
1.用于范围读取通道场景
当您需要不断地从通道中读取数据时。
原则
使用for-range读取通道,既安全又方便。当通道关闭时,for循环会自动退出,不需要主动监控通道是否关闭,可以防止关闭的通道被读取,导致读取的数据为通道中存储的数据类型的零值。
使用
x :=range ch { fmt . println(x)} 2。使用v,ok :=-ch select操作确定通道是否关闭场景。
v,ok :=-ch选择操作决定通道是否关闭。
原则
ok的结果和意义:
-`真的:我读了频道数据,不确定是否要关闭。可能通道还有保存的数据,但是通道关闭了。-`false `:通道关闭,不读取数据。从关闭的通道中读取的值是通道传输的数据类型的零值,该值可能是发送方发送的,也可能是通道关闭。
_,ok :=-ch与select一起使用。当ok为假时,意味着通道已经关闭。原因解释如下。_,ok :=-ch对应的函数是funcchan recv (c * h chan,epunsafe.pointer,block bool)(选中,收到bool)。参考块表示当前goroutine是否可以被阻塞。block为false时,表示选择操作,当前goroutine的通道中的操作不能被阻塞;否则,这是正常操作(即_,ok不在选择中)。选择的返回值代表当前操作是否成功,主要针对选择服务,接收的返回值代表是否从通道读取了有效值。它有三种返回值情况:
Block为false,即如果通道为空,将返回(false,false),这意味着选择操作失败,没有收到任何值。
否则,如果通道已经关闭并且没有数据,则接收数据的变量ep被设置为零并返回(true,false),这意味着选择操作成功,但是通道已经关闭并且没有读取有效值。
否则,在读取有效数据的其他情况下,返回(true,true)。
我们来考虑_,ok :=-ch和select一起使用的情况。
1:当chanrecv返回(false,false)时,本质是select操作失败,所以相关case会阻塞,不被执行,如下面的代码:
funmain(){ ch :=make(chanint)select { casev,ok 3360=-ch 3360 fmt . printf(v 3360% v,ok3360% v \ n,v,ok)default 3360 fmt . println(nothing)/
funmain(){ ch :=true(chanint)//Add close(ch)select { casev _,ok 3360=-ch 3360 fmt . printf(v 3360% v,ok3360% v \ n,v,ok)//v3366
最后,当ok为假时,就只有情况2了。这个时候通道肯定已经关闭了,所以我们可以在select中使用它。
ok判断channel是否已经关闭。
用法
下面例子展示了,向channel写数据然后关闭,依然可以从已关闭channel读到有效数据,但channel关闭且没有数据时,读不到有效数据,ok为false,可以确定当前channel已关闭。
//demo_select6.gofuncmain(){ ch:=make(chanint,1) //发送1个数据关闭channel ch -1 close(ch) print( closechannel\n ) //不停读数据直到channel没有有效数据 for{ select{ casev,ok:= -ch: print( v: ,v, ,ok: ,ok, \n ) if!ok{ print( channelisclose\n ) return default: print( nothing\n )//结果//closechannel//v:1,ok:true//v:0,ok:false//channelisclose
更多见golang_step_by_step/channel/ok仓库中ok和select的示例,或者阅读channel源码。
3. 使用select处理多个channel
场景
需要对多个通道进行同时处理,但只处理最先发生的channel时
原理
select可以同时监控多个通道的情况,只处理未阻塞的case。当通道为nil时,对应的case永远为阻塞,无论读写。特殊关注:普通情况下,对nil的通道写操作是要panic的。
用法
//分配job时,如果收到关闭的通知则退出,不分配jobfunc(h*Handler)handle(job*Job){select{caseh.jobCh -job:returncase -h.stopCh:return}}4. 使用channel的声明控制读写权限
场景
协程对某个通道只读或只写时
目的:
使代码更易读、更易维护,
防止只读协程对通道进行写数据,但通道已关闭,造成panic。
用法
如果协程对某个channel只有写操作,则这个channel声明为只写。
如果协程对某个channel只有读操作,则这个channe声明为只读。
//只有generator进行对outCh进行写操作,返回声明// -chanint,可以防止其他协程乱用此通道,造成隐藏bugfuncgenerator(intn) -chanint{outCh:=make(chanint)gofunc(){fori:=0;i i++{outCh -i}}()returnoutCh//consumer只读inCh的数据,声明为 -chanint//可以防止它向inCh写数据funcconsumer(inCh -chanint){forx:=rangeinCh{fmt.Println(x)}}5. 使用缓冲channel增强并发
场景
异步
原理
有缓冲通道可供多个协程同时处理,在一定程度可提高并发性。
用法
//无缓冲ch1:=make(chanint)ch2:=make(chanint,0)//有缓冲ch3:=make(chanint,1)
//使用5个`do`协程同时处理输入数据functest(){inCh:=generator(100)outCh:=make(chanint,10)fori:=0;i 5;i++{godo(inCh,outCh)}forr:=rangeoutCh{fmt.Println(r)}funcdo(inCh -chanint,outChchan -int){forv:=rangeinCh{outCh -v*v}}6. 为操作加上超时
场景
需要超时控制的操作
原理
使用select和time.After,看操作和定时器哪个先返回,处理先完成的,就达到了超时控制的效果
用法
funcdoWithTimeOut(timeouttime.Duration)(int,error){ select{ caseret:= -do(): returnret,nil case -time.After(timeout): return0,errors.New( timeout )funcdo() -chanint{ outCh:=make(chanint) gofunc(){ //dowork returnoutCh}7. 使用time实现channel无阻塞读写
场景
并不希望在channel的读写上浪费时间
原理
是为操作加上超时的扩展,这里的操作是channel的读或写
用法
funcunBlockRead(chchanint)(xint,errerror){ select{ casex= -ch: returnx,nil case -time.After(time.Microsecond): return0,errors.New( readtimeout )funcunBlockWrite(chchanint,xint)(errerror){ select{ casech -x: returnnil case -time.After(time.Microsecond): returnerrors.New( readtimeout )}
注:time.After等待可以替换为default,则是channel阻塞时,立即返回的效果
8. 使用close(ch)关闭所有下游协程
场景
退出时,显示通知所有协程退出
原理
所有读ch的协程都会收到close(ch)的信号
用法
func(h*Handler)Stop(){close(h.stopCh)//可以使用WaitGroup等待所有协程退出//收到停止后,不再处理请求func(h*Handler)loop()error{for{select{casereq:= -h.reqCh:gohandle(req)case -h.stopCh:return}}}9. 使用chan struct{}作为信号channel
场景
使用channel传递信号,而不是传递数据时
原理
没数据需要传递时,传递空struct
用法
//上例中的Handler.stopCh就是一个例子,stopCh并不需要传递任何数据//只是要给所有协程发送退出的信号typeHandlerstruct{stopChchanstruct{}reqChchan*Request}10. 使用channel传递结构体的指针而非结构体
场景
使用channel传递结构体数据时
原理
channel本质上传递的是数据的拷贝,拷贝的数据越小传输效率越高,传递结构体指针,比传递结构体更高效
用法
reqChchan*Request//好过reqChchanRequest11. 使用channel传递channel
场景
使用场景有点多,通常是用来获取结果。
原理
channel可以用来传递变量,channel自身也是变量,可以传递自己。
用法
下面示例展示了有序展示请求的结果,另一个示例可以见另外文章的版本3。
packagemainimport( fmt math/rand sync time funcmain(){ reqs:=[]int{1,2,3,4,5,6,7,8,9} //存放结果的channel的channel outs:=make(chanchanint,len(reqs)) varwgsync.WaitGroup wg.Add(len(reqs)) for_,x:=rangereqs{ o:=handle( wg,x) outs -o gofunc(){ wg.Wait() close(outs) //读取结果,结果有序 foro:=rangeouts{ fmt.Println( -o)//handle处理请求,耗时随机模拟funchandle(wg*sync.WaitGroup,aint)chanint{ out:=make(chanint) gofunc(){ time.Sleep(time.Duration(rand.Intn(3))*time.Second) out -a wg.Done() returnout} 相关文章
十大巅峰网游小说(十大公认网游小说神作推荐)
百度网盘登陆入口(百度网盘共享群的正确使用方法)
恶人传评价(《恶人传》以暴制暴成了救赎)
百度网盘登录入口(百度网盘安装方法)
番禺中学排名(番禺区热门学校盘点)
马路标志(交通安全标示大全及图解)
苹果序列号是哪个(iPhone序列号知识扫盲)
故宫太和殿介绍(故宫的太和殿为什么叫金銮殿)
东营人均gdp(中国人均GDP前15强城市)
陆贞原型(陆贞传奇的原型各个奇葩)
硫酸铜什么颜色(硫酸铜的用途与危害)
小米平板4参数(小米平板4参数全曝光)
更多channel的中文意思(channel的例句)相关信息请关注本文章,本文仅仅做为展示!
Tags: 网络趣事
很赞哦! ()
相关文章
随机图文
留言与评论 (共有 条评论) |