繁体   English   中英

Go频道上的Noob

[英]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循环的,因此这意味着循环的第一个迭代将简单地闲置着,等待直到有需要读取的内容。

然后fibonaccifibonacci功能启动,并将数据推入通道。 这将使循环唤醒并开始打印。

我希望现在更有意义。

我为您提供了上面代码的较短版本,我认为应该更容易理解。 (我在下面解释了差异。)请考虑以下因素:

// 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM