当通道被缓冲时,这意味着在缓冲区已满之前,它不会阻止。一旦缓冲区填充,发送Goroutine将在尝试将其添加到频道中时阻塞。
这意味着这将阻止:
c := make(chan int)
c <- 1 // Block here, this is unbuffered !
println(<-c)
这将是 还 堵塞:
c := make(chan int, 2)
c <- 1
c <- 2
c <- 3 // Block here, buffer is full !
println(<-c)
但是 观点 Goroutines和渠道正是同时运行的,因此这将起作用:
c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c) // ... this line is reached in the main goroutine
同样:
c := make(chan int, 2)
go func() { // `go ...` spawns a goroutine
c <- 1 // Buffer is not full, no block
c <- 2 // Buffer is not full, no block
c <- 3 // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine
在您的示例中,您产生了四个不同的goroutines,它们全部将四个数字写入同一缓冲通道。由于缓冲区为2 <16,他们最终会阻止
但是问题的症结在于,GO政策是 只等待主要的goroutine:
程序执行首先初始化主包,然后调用函数主。当功能主返回时,程序退出。它不会等待其他(非曼)goroutines完成。
这意味着在您的第一个示例中, 主要的 Goroutine到达线时正在封锁 c <- 3
. 。由于没有其他Goroutine能够做任何可能取消阻止它的事情,因此运行时发现该程序已陷入僵局并报告了错误。
但是,在您的第二个示例中, 产卵 Goroutines Block,而主要的块一直静静地持续到达到其处决结束为止,此时,所有(封锁的)产卵的Goroutines被静静地杀死,并且没有报告任何错误。