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

网站建设技术思维导图最新办公室设计

网站建设技术思维导图,最新办公室设计,网站里面内外链接如何做,万能小偷程序做网站概述 这里又有多路复用,但是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/658084/

相关文章:

  • 模板建站常规流程无人机网站建设
  • 怎么制作网站卖电子文件网站服务器的搭建
  • e时代网站制作黑河seo
  • 个人优秀网站欣赏广州网站建设制作价格
  • 北京城乡和住房建设部网站济南哪里有做网站的公司
  • 智能建站代理网站内链怎么做更好
  • 怎么健免费网站吗郑州效果图设计工作室
  • 网站开发合同支付wordpress图片集插件
  • ps做网站的效果图如何推广游戏
  • 青岛正一品网站建设it网站开发
  • 绵阳建设网站pc网站建设
  • 面包店网站功能建设与栏目划分icons8
  • 提供免费空间的网站宁波谷歌优化
  • 企业所得税是指什么嘉兴seo外包公司费用
  • 公司网站建设济宁徐州市城乡建设局网站
  • 天津做国外网站公司网站建设合同电子版
  • 文山网站开发wordpress转成APP
  • 河南省建设监理协会网站证书查询望野拼音
  • 市桥网站建设哪家好高质量的南昌网站建设
  • 案例展示在网站中的作用网站修改flashfxp上传多久生效
  • 环保局网站建设烟台网站制作效果
  • 网站开发用什么电脑好wordpress读者墙
  • 做卡盟网站网站优化 网站建设公司
  • 电商网站首页图片怎样用织梦做音乐网站
  • 网站开发应如何入账wordpress论坛哪个功能全面
  • 怎么样自己做最简单的网站网上企业名称申请入口
  • 济南网站网站建设360网站安全检测
  • 济南网站建设托管合肥的网站建设公司哪家好
  • 常州建设公司网站价格网站
  • 上海网站建设极简慕枫赣州章贡区房价