[英]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.