我正在学习 Go 语言。这是我遇到的一个例子。有人可以解释一下这里发生了什么吗?package mainimport "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") } }}输出:DefaultDefaultProgram Exited如果我注释掉默认部分//default:// fmt.Println("Default")输出变为:received onereceived twoProgram exited.default案例的存在如何改变通道阻塞的工作方式?
2 回答
慕的地6264312
TA贡献1817条经验 获得超6个赞
这与select
语句在 Go 中的工作方式有关。
如果可以进行一个或多个通信,则通过统一伪随机选择选择可以进行的单个通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,“select”语句会阻塞,直到至少有一个通信可以继续。
因此,如果没有默认情况,代码将一直阻塞,直到任一通道中的某些数据可用。它隐式地等待其他 goroutines 唤醒并写入它们的通道。
当您添加 default case 时,很可能select
在其他 goroutines 从睡眠中醒来之前到达该语句。
因此,由于(尚)没有可用数据,并且存在默认情况,因此会执行默认情况。此操作进行两次,耗时不到 1 秒。所以程序在任何 go 例程有机会唤醒并写入通道之前终止。
请注意,这在技术上是一种竞争条件;绝对不能保证循环的 2 次迭代会在任何 go 例程唤醒之前运行,因此理论上即使在默认情况下也可能有不同的输出,但实际上这是极不可能的。
- 2 回答
- 0 关注
- 284 浏览
添加回答
举报
0/150
提交
取消