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

Go 无缓冲通道是否等待数据?,go,locking,buffer,channel,Go,Locking,Buffer,Channel,我有这个计划: 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("

我有这个计划:

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")
}
为什么那些无缓冲通道
ch1
ch2
没有在main中被阻塞

如果我没有在
main
中调用
f1
/
f2
,它将报告
死锁
错误

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

请您解释一下他们的行为好吗?

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

因此,您可以启动
f1()
f2()
作为新的goroutines,然后
main()
休眠。同时
f1()
f2()
正在等待来自
ch1
ch2
的数据

然后
main()
唤醒,并尝试在
ch1
上发送一个值。这是正常的,因为有一个goroutine准备从它接收(
f1()
)。然后
main()
尝试发送
ch2
,这也没问题,有
f2()
准备接收

然后
main()
返回,应用程序结束(它不等待其他goroutine打印)


如果您没有将
f1()
f2()
作为新的goroutines启动,当
main()
到达send语句时,将没有人准备好接收来自通道的消息,因为它是无缓冲的,它将被阻塞。由于不再有goroutines运行,这是一个死锁。

通常的惯例是谈论
缓冲的
无缓冲的
通道。其中
缓冲
通道具有
缓冲长度>1
,允许
推送
,而无需等待
弹出
操作。另一方面,由于
无缓冲
通道的缓冲区为空,因此每次
推送
操作都需要另一个例程的
弹出
no buffered channel will wait?
main exits