无缓冲通道是否等待数据?

does unbuffered channel wait for data?

我有这个程序:

package main

import (
    "fmt"
    "time"
)

var ch1 = make(chan int)
var ch2 = make(chan int)

func f1() {
    select {
    case <-ch1:
        fmt.Println("ch1")
    }
}
func f2() {
    select {
    case <-ch2:
        fmt.Println("ch2")
    }
}
func main() {
    go f1()
    go f2()
    time.Sleep(2 * time.Second)
    fmt.Println("no buffered channel will wait?")
    ch1 <- 1
    ch2 <- 2
    fmt.Println("main exits")
}

我希望,只要 f1 和 f2 不打印任何东西,就意味着 ch1 和 ch2 里面什么也没有,所以 ch1<-1ch2<-2 应该阻塞?

但是当 运行 时,它会打印:

no buffered channel will wait?
main exits

为什么那些无缓冲通道 ch1ch2 没有在主通道内被阻塞?

如果我不在main中调用f1/f2,就会报dead lock错误。

我不明白 f1/f2 对 ch1/ch2 做了什么。

你能帮忙解释一下他们的行为吗?

f1()f2()都有接收操作。这些是阻塞操作:只要通道上没有人发送任何东西,它们就会等待

所以你启动 f1()f2() 作为新的 goroutines,然后 main() 休眠。同时 f1()f2() 正在等待来自 ch1ch2 的数据。

然后 main() 醒来,并尝试在 ch1 上发送一个值。这没问题,因为有一个 goroutine 准备好从它接收 (f1())。然后 main() 尝试在 ch2 上发送,这也可以,f2() 已准备好接收。

然后main()returns,app结束(不等待其他goroutines打印)。

如果你不启动 f1()f2() 作为新的 goroutines,当 main() 到达发送语句时,将没有人准备好从通道接收,并且由于它是无缓冲的,它会阻塞。由于不会再有任何 goroutines 运行,这是一个死锁。