我试图了解缓冲频道的工作方式,并为其编写代码段
package main
import (
"fmt"
)
func squares(c chan int) {
for i := 0; i < 4; i++ {
num := <-c
fmt.Println(num * num)
}
}
func main() {
fmt.Println("main() started")
c := make(chan int, 3)
go squares(c)
c <- 1
c <- 2
c <- 3
c <- 4 // blocks here
fmt.Println("main() stopped")
}
根据我期望该程序的表现方式,主goroutine启动并持续到c <-4,直到c <-4被阻止,并且控件转移到Square Goroutine(由于缓冲区容量为3)。正方形goroutine中的循环一直持续到第四次迭代,此时通道为空。空通道上的读取操作正在阻止,因此控件返回到主goroutine。那时,对频道的写操作(C <-4)被执行,我们打印"main() stopped"并结束程序。
这意味着我希望输出是
main() started
1
4
9
main() stopped
但是我得到了一个输出,
main() started
1
4
9
16
main() stopped
如何?我是否缺少有关channel如何工作的东西?
分析解答
那不是频道的工作方式。
Goroutines同时运行。这意味着,当goroutine发送到缓冲通道时,另一个goroutine等待从该频道接收的gor可以立即接收它。它不会等待频道填充。
至于程序的结束,当您将最后一个号码发送到频道时,无法保证Goroutine会在程序结束之前拾起并打印输出,因为您不在等待Goroutine完成。因此,通过运气,它可以运行并打印输出。将在其他执行中不会发生其他执行,并且该程序在Goroutine可以打印输出之前终止。