我正在编写基本遍历树的Walk function in the go tutorial。我的工作是什么:
package main
import (
"fmt"
"code.google.com/p/go-tour/tree"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk__helper(t *tree.Tree, ch chan int) {
if (t == nil) {
return
}
Walk__helper(t.Left, ch)
ch <- t.Value
Walk__helper(t.Right, ch)
}
func Walk(t *tree.Tree, ch chan int) {
Walk__helper(t, ch)
close(ch)
}
func main() {
ch := make(chan int)
go Walk(tree.New(1), ch)
for v := range ch {
fmt.Println(v)
}
}
为什么我必须使用go Walk(tree.New(1), ch)
而不仅仅Walk(tree.New(1), ch)
?
我的印象是go
关键字基本上产生了一个新线程。在这种情况下,我们遇到问题,因为for循环可能在子例程完成之前运行。
奇怪的是,当我取出go
关键字时,我遇到了僵局。这对我来说是违反直觉的。 go
关键字到底在做什么?
答案 0 :(得分:4)
当与频道结合时,此处的关键点是range
。
当你range
通过一个频道(在这种情况下,ch
)时,它会在迭代循环之前等待频道上的项目发送。这是一个安全的,阻止&#34;动作,在等待频道接收项目时不会死锁。
不使用goroutine时会发生死锁,因为您的频道未被缓冲。如果你不使用goroutine,那么方法调用是同步的,Walk
会在通道上放置一些东西..然后它会阻塞,直到弹出它为止。它永远不会被弹出...因为方法调用是同步的。
我的印象是go关键字基本上产生了一个新线程
..这是不正确的。需要了解更多重要的实施细节才能了解其中发生的情况。您应该将goroutine的思维过程与线程分开..只需将goroutine视为同时执行的代码段,而不是&#34;线程&#34;。