无缓冲通道阻止接收器,直到通道上的数据可用。我不清楚这种阻塞在同一个通道上的多个接收器如何表现(比如使用goroutines时)。只要该频道上没有数据发送,我相信他们都会阻止 但是,一旦我向该频道发送单个值,会发生什么?哪个接收器/ goroutine将获取数据并因此解除阻塞?他们都是?排在第一位?随机?
答案 0 :(得分:13)
单个随机(非确定性)将接收它。
请参阅语言spec:
执行"选择"声明分几步进行:
- 对于语句中的所有情况,接收操作的通道操作数以及发送的通道和右侧表达式 语句在输入时按源顺序精确评估一次 "选择"声明。结果是一组要接收的通道 from或send to,以及要发送的相应值。任何一方 无论哪个(如果有的话)都会发生评估中的影响 选择通信操作以继续。表达方式 带有短变量声明的RecvStmt的左侧或 作业尚未评估。
- 如果一个或多个通信可以继续,可以通过统一的伪随机选择选择可以继续进行的单个通信。 否则,如果存在默认情况,则选择该情况。如果有 没有默认情况下,"选择"声明阻止至少一个 通讯可以继续。
- 除非所选案例是默认情况,否则将执行相应的通信操作。
- 如果所选案例是具有短变量声明或赋值的RecvStmt,则左侧表达式为 评估并分配收到的值(或值)。
- 执行所选案例的陈述清单。
醇>
答案 1 :(得分:4)
默认情况下,goroutine通信为synchronous
和unbuffered
:在接收方接受该值之前,发送不会完成。必须有一个接收器准备好从通道接收数据,然后发送者可以直接将其交给接收器。
所以通道发送/接收操作阻塞,直到另一方准备就绪:
1。通道上的发送操作会阻塞,直到接收器可用于同一频道:如果ch
上的值没有收件人,则不能放入其他值这个频道。反过来说:当频道不为空时,ch
不能发送新值!因此,发送操作将等到ch
再次可用。
2. 频道的接收操作会阻塞,直到发送者可用于同一频道:如果频道中没有值,则接收器会阻止。
以下示例说明了这一点:
package main
import "fmt"
func main() {
ch1 := make(chan int)
go pump(ch1) // pump hangs
fmt.Println(<-ch1) // prints only 0
}
func pump(ch chan int) {
for i:= 0; ; i++ {
ch <- i
}
}
因为没有接收器,goroutine会挂起并仅打印第一个数字。
要解决此问题,我们需要定义一个新的goroutine,它在无限循环中从通道读取。
func receive(ch chan int) {
for {
fmt.Println(<- ch)
}
}
然后在main()
:
func main() {
ch := make(chan int)
go pump(ch)
receive(ch)
}
答案 2 :(得分:0)
如果程序允许在单个频道上接收多个goroutine,则发送方正在广播。每个接收器都应具有相同的数据处理能力。因此,go运行时使用哪种机制来决定要运行Cf的许多goroutine接收器中的哪一个都没有关系。 https://github.com/golang/go/issues/247。但是,如果通道未缓冲,则每个发送的项目仅运行一个。