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

昆明网站建设logovi深圳做app开发

昆明网站建设logovi,深圳做app开发,鄂州seo,营销网站制作概述 这里又有多路复用,但是Go中的这个多路复用不同于网络中的多路复用。在Go里,select用于同时等待多个通信操作(即多个channel的发送或接收操作)。Go中的channel可以参考我的文章:逐步学习Go-并发通道chan(channel)…

概述

这里又有多路复用,但是Go中的这个多路复用不同于网络中的多路复用。在Go里,select用于同时等待多个通信操作(即多个channel的发送或接收操作)。Go中的channel可以参考我的文章:逐步学习Go-并发通道chan(channel)

拆字解释

  • 多路:指的是多个channel操作路径。你可以在select块中定义多个case,每个case对应一个channel上的I/O操作(发送或接收)。

  • 复用:指的是select的功能,它可以监听多个channel上的事件,并且仅当其中一个channel准备就绪时才会执行相关操作。这样,单个goroutine可以高效地等待多个并发事件而不是单个事件。

复用的是goroutine,一个goroutine使用select可以监听多个信道。

整体来讲:Select就是为channel设计的。

这张图是参考大佬Dravenss画的

select语法

Go语言中的select关键字功能在概念上与操作系统的select类似,区别在于Go的select是用于goroutine监听多个channel的可读或可写状态。

Go的select允许在channel上进行非阻塞收发,同时当多个channel同时响应时,select会随机执行其中的一个case。

Go的select语句可以包含一个default分支,使得在没有channel准备好时,不会阻塞goroutine,而是执行default分支。

select {case <-ch:println("recieved")case <-time.After(10 * time.Second):println("Timeout")default:printStr = "Hello Select"}

COPY

接下来我们来看场景用例。

在下面的场景测试用例中,我们定义了三个channel: ch1, ch2和ch3。

select只有一个case条件满足

我们创建完成三个channel以后,我们只想ch1发送消息,那么在select三个channel时只有 case <- ch1可以满足,用例执行会输出"Recieved ch1"。

file


func TestSelect_ShouldRecvChan1_WhenChan1CaseWasFullfilled(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)chans := []chan int{ch1, ch2, ch3}var wg sync.WaitGroupwg.Add(1)go func() {chans[0] <- 1wg.Done()}()wg.Wait()select {case <-ch1:println("Recieved ch1")case <-ch2:println("Recieved ch2")case <-ch3:println("Recieved ch3")case <-time.After(10 * time.Second):println("Timeout")default:}}

COPY

select有多个case条件满足

在这个场景中,我们使用三个goroutine向三个channel都发送了消息,然后等待所有的goroutine执行完成确保3个channel都接收到了消息,那么select会随机选择一个case条件执行(如果自己测试需要多执行几次,因为不止下一次会执行那个case分支)。

如果select中的多个case同时满足,Go语言如何进行选择。Go语言官方文档规定,当多个case都可以运行时,Go会按照"伪随机"的方式来选择一个case执行。这个"伪随机"是指,它不是完全随机的,而是通过一定的算法进行选择,以防止某个channel在高并发的情况下,出现饿死(被忽略)的情况。

file


func TestSelect_ShouldRandomEnterCaseBranch_WhenAllChannelsCaseWereFullfilled(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)chans := []chan int{ch1, ch2, ch3}var wg sync.WaitGroupwg.Add(3)for i := 0; i < 3; i++ {go func(i int) {chans[i] <- 1wg.Done()}(i)}wg.Wait()select {case <-ch1:println("Recieved ch1")case <-ch2:println("Recieved ch2")case <-ch3:println("Recieved ch3")case <-time.After(10 * time.Second):println("Timeout")default:}}

COPY

select没有条件满足-阻塞(Deadlock)

在这个场景,我们只是创建了3个channel,但是没有向三个channel发送消息,那么执行select时go会panic, 错误信息为:Deadlock。

file


func TestSelect_ShouldBlock_WhenNoCaseWasFullfilled(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)select {case <-ch1:println("Recieved ch1")case <-ch2:println("Recieved ch2")case <-ch3:println("Recieved ch3")}}

COPY

select没有条件满足-超时

在这个场景中,我们创建了三个channel,然后没有向这三个channel中发送消息,最后我们使用select尝试从三个channel中接收消息,但是我们在case中增加了一个超时检测。

在这个场景中,select会在10秒后执行 case <-time.After(10 * time.Second):分支因为管道条件没有被满足且没有default

file


func TestSelect_ShouldTimeout_WhenNoCaseWasFullfilled(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)select {case <-ch1:println("Recieved ch1")case <-ch2:println("Recieved ch2")case <-ch3:println("Recieved ch3")case <-time.After(10 * time.Second):println("Timeout")}}

COPY

select没有条件满足-default

在这个场景中,代码和上面的差别在于我们添加了default分支,添加了default后如果所有case没有条件满足则执行default分支,所以你执行这个用例控制台会打印Default

file


func TestSelect_ShouldRunDefaultBranch_WhenNoCaseWasFullfilledAndHasDefaultBranch(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)select {case <-ch1:println("Recieved ch1")case <-ch2:println("Recieved ch2")case <-ch3:println("Recieved ch3")case <-time.After(10 * time.Second):println("Timeout")default:println("Default")}}

COPY

select关闭的channel接收

在这个场景中,我们创建3个channel然后理解关闭,最后使用select来读取三个channel,那么根据关闭后chnanel的定义:channel在关闭后永远都可以读取,那么select 的case条件可以被满足且随机选择一个case分支执行,只是读取到的都是“0”值。

注意:0值这个是根据不同类型而不一样的,而且go是严格类型检查,nil是不通用的


func TestSelect_ShouldRecvZeroValue_WhenSelectFromClosedChannel(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)close(ch1)close(ch2)close(ch3)select {case value := <-ch1:if value == 0 {println("Recieved zero value from ch1")} else {println("Recieved ch1")}case value := <-ch2:if value == 0 {println("Recieved zero value from ch2")} else {println("Recieved ch2")}case value := <-ch3:if value == 0 {println("Recieved zero value from ch3")} else {println("Recieved ch3")}case <-time.After(10 * time.Second):println("Timeout")default:println("Default")}
}

COPY

select 在关闭的channel上发送

在这个场景中,我们向通过select的case分支来向关闭的channel发送数据,根据go channel的定义:会发生panic。

如下截图,我们的UT显示PASS,表示发生了Panic,当然你也可以改变一下把assert.Panics注释掉,直接执行select的,那么你会得到第二张图的结果:"send on closed channel"

file

file

func TestSelect_ShouldPanic_WhenSendToClosedChannel(t *testing.T) {ch1 := make(chan int, 1)ch2 := make(chan int, 1)ch3 := make(chan int, 1)close(ch1)close(ch2)close(ch3)assert.Panics(t, func() {select {case ch1 <- 1:println("send ch1")case ch2 <- 1:println("send ch2")case ch3 <- 1:println("send ch3")case <-time.After(10 * time.Second):println("Timeout")default:println("Default")}})}

参考: 逐步学习Go-Select多路复用 – FOF编程网 

http://www.yayakq.cn/news/801547/

相关文章:

  • 放置在网站根目录下合肥手机建站模板
  • 重庆网站建设与推广wordpress编辑区块报警
  • wordpress摘要添加省略号网站导航如何优化
  • 上海浦东网站设计公司上海关键词优化排名软件
  • 河南发布紧急通知网站seo优化要怎么做
  • 企业网站的分类vi设计公司排行榜
  • 网站优化哪个公司好wordpress免费网站模板下载
  • 百度站长平台账号购买网站建设提供商
  • 作品集的个人网站怎么做西安可以做网站的
  • wordpress网站制作价格网站建设销售找客源
  • 上海协策网站制作网站建设的主要功能有哪些
  • 快速网站推广优化高新区网站建设
  • 搭建门户网站费用是多少建设银行东莞招聘网站
  • 开发网站如何赚钱怎么申请自己的小程序
  • 网贷之家网站建设网站seo的重要性
  • 南宁在那里推广网站专门做算法项目的网站
  • 免费的php网站模板百度入驻绍兴
  • 浅谈电子商务网站建设与管理的理解东莞外贸网站推广建设
  • gofair做网站个人主页类网站开发背景
  • 衡水做阿里巴巴网站安徽六安金寨县
  • 网站建设 后端开发软件搜索引擎优化是什么
  • 一流学科建设专题网站深圳市浩天建设网站
  • 淘宝客网站制作网站更换服务器 seo
  • 三角网站建设企业免费网站推广公司
  • 免费建立企业网站大连旅游必去景点
  • 中山做网站哪家好上海做网站比较好的
  • 北京建设企业协会网站免费行情软件app网站大全下载免费入口
  • 建网站到底需要多少钱如何免费建企业网站
  • 建设银行网站登录不上做一个小说网站需要多少钱
  • 个人官方网站怎么建设自己做网站前期困难吗