Select Go中的通道阻塞是如何工作的?
我在学围棋。这是我遇到的一个例子。有人能解释一下这里发生了什么吗Select Go中的通道阻塞是如何工作的?,select,go,channel,Select,Go,Channel,我在学围棋。这是我遇到的一个例子。有人能解释一下这里发生了什么吗 package main import "time" import "fmt" func main() { c1 := make(chan string) c2 := make(chan string) go func() { time.Sleep(time.Second * 1) c1 <- "one" }() go func() {
package main
import "time"
import "fmt"
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
go func() {
time.Sleep(time.Second * 2)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
default:
fmt.Println("Default")
}
}
}
如果我注释掉默认的部分
//default:
// fmt.Println("Default")
输出变为:
received one
received two
Program exited.
default
案例的存在如何改变通道阻塞的工作方式?在至少一个案例准备就绪之前,select
语句阻塞。Go语言规范:
如果一个或多个通信可以进行,则通过均匀伪随机选择选择可以进行的单个通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,“select”语句阻塞,直到至少一个通信可以继续
在原始代码中,default
案例在循环的两次迭代中都已准备就绪,因为在c1
或c2
上发送任何内容之前存在延迟
删除
default
案例后,select
语句必须等待数据在c1
或c2
中可用,这与select
语句在Go中的工作方式有关
发件人:
如果一个或多个通信可以继续,则单个通信
可以通过均匀伪随机选择继续。
否则,如果存在默认情况,则选择该情况。如果有
如果没有默认情况,“select”语句将阻塞,直到至少有一个
所有通信都可以继续
因此,如果没有默认情况,代码将阻塞,直到在任一通道中都有可用的数据。它隐式地等待其他goroutine醒来并写入它们的通道
添加默认情况时,很可能在其他goroutine从睡眠中醒来之前到达select
语句
因此,由于没有可用的数据,并且存在默认情况,因此将执行默认情况。这样做两次,所需时间不到1秒。因此,程序在任何go例程有机会醒来并写入通道之前终止
请注意,这在技术上是一种竞赛条件;绝对不能保证循环的2次迭代将在任何go例程唤醒之前运行,因此理论上,即使在默认情况下,也有可能有不同的输出,但在实践中,这是极不可能的。
请参见上面给出的链接以获取执行示例。如果没有其他案例准备就绪,则执行默认案例。
在golang区块中选择,直到其中一个案例准备就绪。因此,删除默认值使其他情况的执行成为可能,否则它是在其他情况之前准备好的情况解释:
Explanation:
c1 := make(chan string) // Creates a channel of type string. [Means only
strings can be sent/received on this channel]
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
// func() is a goroutine [As go keyword is placed before, if no go keyword
here, then it is a simple function].
time.Sleep(time.Second * 1) // here this func() goroutine will sleep for a
second before passing a value to the channel c1.
c1 <- "one"// value "one" is passed to this channel.
select statement: Here it waits for the goroutines to complete it's task.
Once a goroutine above finishes, it matches it's case and executes the
statements.
c1:=make(chan string)//创建string类型的通道。[仅指
可在此频道上发送/接收字符串]
go func(){
时间。睡眠(时间。秒*1)
c1谢谢你的澄清。谢谢你的投票。我有点恼火,因为我先发布了我的答案。我选择了另一个答案,因为它包括了程序退出的原因,甚至在go例程完成他们的工作之前。我想我已经在这里讲过了:“在原始代码中,default
案例在循环的两次迭代中都已准备就绪,因为在c1
或c2
上发送任何内容之前存在延迟。“@MichaelLaszlo在看到您的评论后,我取消了对已接受答案的投票,并对您的答案进行了投票。链接是有用的,但如果您可以将相关代码发布到,就好像链接消失了一样,那就更好了。谢谢。这是非常没有帮助的
Explanation:
c1 := make(chan string) // Creates a channel of type string. [Means only
strings can be sent/received on this channel]
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
// func() is a goroutine [As go keyword is placed before, if no go keyword
here, then it is a simple function].
time.Sleep(time.Second * 1) // here this func() goroutine will sleep for a
second before passing a value to the channel c1.
c1 <- "one"// value "one" is passed to this channel.
select statement: Here it waits for the goroutines to complete it's task.
Once a goroutine above finishes, it matches it's case and executes the
statements.