为什么不执行子程序

时间:2017-07-03 08:08:04

标签: go

我正在学习,按照在线教程"参观Go"。

在此练习中:https://tour.golang.org/concurrency/10

在继续解决问题之前,我想尝试一些简单的事情:

func Crawl(url string, depth int, fetcher Fetcher) {
    fmt.Println("Hello from Crawl")
    if depth <= 0 {
        return
    }
    body, urls, err := fetcher.Fetch(url)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("found: %s %q\n", url, body)
    for _, u := range urls {
        fmt.Println("in loop with u = %s", u)
        go Crawl(u, depth-1, fetcher) //I added "go" here
    }
}

在递归调用go之前,我唯一添加的是Crawl命令。我预计它不应该改变很多行为。

然而打印输出是:

Hello from Crawl
found: http://golang.org/ "The Go Programming Language"
in loop with u =  http://golang.org/pkg/
in loop with u =  http://golang.org/cmd/

我希望循环的每次迭代都能看到Hello from Crawl。 为什么我的Crawl子程序没有被执行?

2 个答案:

答案 0 :(得分:2)

您的goroutines已经开始,但在您执行您想要的操作之前结束,因为main()已完成。执行goroutine与主程序(如线程)无关,但在程序停止时将终止。因此,您需要WaitGroup等待goroutine完成工作,或者只需调用time.Sleep()使主程序暂停一段时间。

答案 1 :(得分:1)

没有什么可以确保你的程序在程序完成之前结束,我会将你的代码重构为类似的东西:

func Crawl(url string, depth int, fetcher Fetcher) {
    fmt.Println("Hello from Crawl")
    if depth <= 0 {
        return
    }
    body, urls, err := fetcher.Fetch(url)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("found: %s %q\n", url, body)
   // Adding waiting group to make sure go routines finishes
    wg := sync.WaitGroup{}
    wg.Add(len(urls))
    for _, u := range urls {
        fmt.Println("in loop with u = %s", u)
        go func() {
           defer wg.Done()
           Crawl(u, depth-1, fetcher)
        }()
    }
    wg.Wait()
}