3 回答
TA贡献1872条经验 获得超3个赞
请记住,通道会阻塞,因此 select 语句如下:
select {
case c <- x: // if I can send to c
// update my variables
x, y = y, x+y
case <-quit: // If I can receive from quit then I'm supposed to exit
fmt.Println("quit")
return
}
没有default案例意味着“如果我不能发送到 c 并且我不能从退出中读取,直到我可以为止。”
然后在你的主进程中,你分离出另一个读取c结果的函数
for i:=0; i<10; i++ {
fmt.Println(<-c) // read in from c
}
quit <- 0 // send to quit to kill the main process.
这里的关键是要记住通道会阻塞,并且您正在使用两个无缓冲通道。使用go分拆第二个功能可以让您消费,c所以fibonacci将继续。
Goroutines 是所谓的“绿色线程”。使用关键字启动函数调用go会将其分拆为一个独立于主执行线运行的新进程。从本质上说,main()和go func() ...同时运行!这很重要,因为我们在此代码中使用了生产者/消费者模式。
fibonacci产生值并将它们发送到c,从 main 产生的匿名 goroutine 消耗来自的值c并处理它们(在这种情况下,“处理它们”只是意味着打印到屏幕上)。我们不能简单地产生所有的值然后消费它们,因为c会阻塞。此外fibonacci将永远产生更多的值(或直到整数溢出),因此即使您有一个具有无限长缓冲区的魔术通道,它也永远不会到达消费者。
TA贡献1865条经验 获得超7个赞
理解这个代码示例有两个关键点:
首先,让我们回顾一下无缓冲通道的工作原理。从文档
如果通道未缓冲,则发送方会阻塞,直到接收方收到该值。
请注意,在代码示例两个通道,c
并且quit
是无缓冲。
其次,当我们使用go
关键字启动一个新的 goroutine 时,执行将与其他例程并行发生。因此,在本例中,我们同时运行两个走程序:常规的启动func main()
,并开始了例行go func()...
内func main()
。
我在这里添加了一些内联注释,这应该会使事情更清楚: package main import "fmt"
func fibonacci(c, quit chan int) {
x, y := 0, 1
for { // this is equivalent to a while loop, without a stop condition
select {
case c <- x: // when we can send to channel c, and because c is unbuffered, we can only send to channel c when someone tries to receive from it
x, y = y, x+y
case <-quit: // when we can receive from channel quit, and because quit is unbuffered, we can only receive from channel quit when someone tries to send to it
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() { // this runs in another goroutine, separate from the main goroutine
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit) // this doesn't start with the go keyword, so it will run on the go routine started by func main()
}
TA贡献1811条经验 获得超6个赞
你已经明白了。
在 go func() 中,我们显然是从 c 打印值,但是 c 中不应该有任何内容吗?我能想到的唯一解释是 go func() 在调用 fibonacci() 之后以某种方式执行。我猜这是一个 goroutine
是的, go 关键字启动了一个 goroutine,所以func()将与fibonacci(c, quit) 同时运行。从 Println 中的通道接收只是阻塞,直到有东西要接收
- 3 回答
- 0 关注
- 158 浏览
添加回答
举报