我正在从有关网络爬虫练习的Go Tour示例中学习go频道。
我的理解是
go func ()
在后台运行func,如果没有阻塞,则只需完成func然后返回即可。
但是下面的go Crawl()似乎什么也没做。我了解这个权利吗?
package main
import (
"fmt"
)
type Fetcher interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
Fetch(url string) (body string, urls []string, err error)
}
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
// TODO: Fetch URLs in parallel.
// TODO: Don't fetch the same URL twice.
// This implementation doesn't do either:
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("u is ", u)
go Crawl(u, depth-1, fetcher)
}
return
}
func main() {
Crawl("https://golang.org/", 4, fetcher)
}
// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult
type fakeResult struct {
body string
urls []string
}
func (f fakeFetcher) Fetch(url string) (string, []string, error) {
if res, ok := f[url]; ok {
return res.body, res.urls, nil
}
return "", nil, fmt.Errorf("not found: %s", url)
}
答案 0 :(得分:2)
当main
包的main
方法返回时,Go程序终止。这样做后,程序(包括所有goroutine)立即退出。参见Go language spec:
通过初始化主程序包然后调用函数main开始程序执行。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。
在这种情况下,您的Crawl
方法产生多个goroutine,并立即返回,而无需同步这些goroutine以等待它们完成。这样做之后,控制流返回到main
,到达函数的末尾并隐式返回,从而暂停程序。请注意,这种交错行为不是确定性的-在某些情况下,您可以从中获取某些goroutine的输出,但是不太可能如此迅速地安排它们的执行。
您需要为Crawl
实现一种机制,以阻止等待它产生的goroutine的结果。有几种执行此操作的机制,最常见和推荐的方法是使用WaitGroup。