簡體   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