我正在学习,按照在线教程"参观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
子程序没有被执行?
答案 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()
}