2017-07-03 92 views
0

我正在学习去,遵循在线教程“围棋之旅”。为什么不去执行子程序

在本练习: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子程序得不到执行?

+0

我同意链接的问题的答案我的也是如此。 –

回答

2

你的房间开始了,但在做完你想做的事之前就结束了,因为你的main()完成了。 goroutines的执行与线程等主程序无关,但在程序停止时会终止。所以你需要一个WaitGroup来等待goroutines完成他们的工作,或者直接调用time.Sleep()来让主程序休眠一段时间。

+0

该教程尚未涵盖'WaitGroup',但是感谢你们两位,至少我现在明白了这个问题。 –

+0

你可以使用频道而不是'WaitGroup',这里的本质就是你需要等待去完成的事实 –

+0

@NathanH不客气,继续前进:) – jfly

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() 
}