我在 go 教程中编写了Walk 函数,该函数基本上是按顺序遍历树的。我有什么作品:package mainimport ( "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关键字在这里到底是做什么的?
1 回答
慕容3067478
TA贡献1773条经验 获得超3个赞
这里的关键点是range
与通道耦合时。
当您range
通过通道(在本例中为ch
)时,它会等待项目在通道上发送,然后再遍历循环。这是一个安全的“阻塞”操作,在等待通道接收项目时不会死锁。
不使用 goroutine 时会发生死锁,因为您的通道没有缓冲。如果你不使用 goroutine,那么方法调用是同步的,Walk
在通道上放一些东西......它会阻塞直到它被弹出。它永远不会弹出......因为方法调用是同步的。
我的印象是 go 关键字基本上会产生一个新线程
..那是不正确的。要了解那里发生的事情,还需要更多重要的实现细节。您应该将 goroutine 的思考过程与线程分开......并且将 goroutine 视为并发执行的一段代码,没有“线程”。
- 1 回答
- 0 关注
- 220 浏览
添加回答
举报
0/150
提交
取消