[英]Noob on channels in Go
我试图绕过Go中的并发模式,但对此#69中的示例感到困惑
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)
}
特别是我看不出来
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
应该工作了,因为我们所做的只是制作频道,现在我们从中“接收”了10次了? 我尝试了其他代码,在这些代码中我创建了一个频道,然后尝试立即从该频道接收消息,但我总是收到错误消息,但这似乎行得通,而且我不太清楚如何操作。 谢谢你的帮助!
fmt.Println(<-c)
将阻塞,直到从通道读取某些内容为止。 由于我们是在单独的goroutine中启动for
循环的,因此这意味着循环的第一个迭代将简单地闲置着,等待直到有需要读取的内容。
然后fibonacci
那fibonacci
功能启动,并将数据推入通道。 这将使循环唤醒并开始打印。
我希望现在更有意义。
我为您提供了上面代码的较短版本,我认为应该更容易理解。 (我在下面解释了差异。)请考虑以下因素:
// http://play.golang.org/p/5CrBSu4wxd
package main
import "fmt"
func fibonacci(c chan int) {
x, y := 0, 1
for {
c <- x
x, y = y, x+y
}
}
func main() {
c := make(chan int)
go fibonacci(c)
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
}
这是一个更直接的版本,因为您的main
功能显然是仅从通道中打印10个值,然后退出。 只要有新的值,就会有一个后台goroutine填充通道。
此备用版本删除了退出通道,因为后台goroutine仅在main()
完成时死掉main()
在这样一个简单的示例中无需显式杀死它)。
当然,此版本也取消了select{}
的使用,这是#69的主题。 但是,查看这两个版本如何完成相同的事情(除了杀死后台goroutine之外),可能有助于理解select
功能。
特别要注意的是,如果fibonacci()
的第一条语句具有time.Sleep()
,则for循环将挂起那么长时间,但最终会起作用。
希望这可以帮助!
PS:刚刚意识到这个版本只是比#68更简单的版本,所以我不确定它会提供多少帮助。 哎呀。 :-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.