为什么我需要用一个新的子程序运行 Walk?

我在 go 教程中编写了Walk 函数,该函数基本上是按顺序遍历树的。我有什么作品:


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关键字在这里到底是做什么的?


RISEBY
浏览 221回答 1
1回答

慕容3067478

这里的关键点是range与通道耦合时。当您range通过通道(在本例中为ch)时,它会等待项目在通道上发送,然后再遍历循环。这是一个安全的“阻塞”操作,在等待通道接收项目时不会死锁。不使用 goroutine 时会发生死锁,因为您的通道没有缓冲。如果你不使用 goroutine,那么方法调用是同步的,Walk在通道上放一些东西......它会阻塞直到它被弹出。它永远不会弹出......因为方法调用是同步的。我的印象是 go 关键字基本上会产生一个新线程..那是不正确的。要了解那里发生的事情,还需要更多重要的实现细节。您应该将 goroutine 的思考过程与线程分开......并且将 goroutine 视为并发执行的一段代码,没有“线程”。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go