我在这里的并发示例:https://tour.golang.org/concurrency/5
这是代码:
package main
import "fmt"
func fibonacci(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x:
x, y = y, x + y
case <- quit:
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<- c)
}
quit <- 0
}()
fibonacci(c, quit)
}
有很多相关内容令我感到困惑,而且巡回赛本身并没有多说。它表示select会等待通信操作,但是我并没有真正了解它在调用fibonacci
之前如何应用于它发送给goroutine的函数。 fmt.Println
被发送到c
频道,但我不知道为什么或如何有意义......
我对此有很多疑问,我希望在了解完第一部分后,一切都会落实到位......
答案 0 :(得分:3)
在代码示例中,goroutine已启动,并一直运行,直到它到达fmt.Println(<- c)
,并打印从c
收到的值。在这个时间i == 0
,我们在第一次迭代中。同时,由于这是在goroutine中运行的,因此main继续执行并调用fibonacci
传递c
和quit
个频道。 fibonacci
功能位于“无限”状态。选择,这意味着如果没有明确地调用return
,就像从quit
频道收到时那样,你永远不会离开。
所以回到main,你调用goroutine,它阻塞直到从通道接收,fibonacci
开始执行并在该通道上发送,提供fibonacci
序列中的下一个数字,直到该循环终止(当i == 10
时)此处的代码向下移动到quit <- 0
,在退出通道上发送。由于您在fibonacci
中进行了无限选择,因此它将始终执行下一个可用情况,它无法继续在c
上发送,因为该频道未缓冲,它只允许一个项目和已填满,而是在quit
案例陈述中移动,因为它已在quit
频道收到某些内容,此时它会打印quit
并返回。
希望有所帮助。某些语言可能不是100%准确。真的只是试图说明这种控制流程是如何工作的。我认为实际上,select等待直到main中的goroutine可以接收它进入c <- x
语句并发送。您可以通过在完成所有操作后尝试从通道中读取项目来观察此情况,这会导致恐慌。实际上他们都在等待彼此,你不能发送一个完整的频道,如果你只是在没有任何其他控制流程(如选择)的情况下阅读它,那么你将阻止,直到那里有东西接受。