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.