我一直在浏览,我已经完成了网络爬虫练习,但我认为我用来打印所有结果的技术可能效率低下。
这是我的代码。我只编辑了抓取和主要功能,所以我只是发布它。以下是练习的链接(http://tour.golang.org/#70)
var used = make(map[string]bool)
func Crawl(url string, depth int, fetcher Fetcher, results chan string) {
if depth <= 0 {
return
}
body, urls, err := fetcher.Fetch(url)
if err != nil {
results <- fmt.Sprintf("%v",err)
return
}
results <-fmt.Sprintf("\nfound: %s %q\n", url, body)
for _,u := range urls {
if used[u] == false {
used[u] = true
go Crawl(u, depth-1, fetcher, results)
}
}
return
}
//------------------------------------------------------------
func main() {
used["http://golang.org/"] = true
results := make(chan string)
go Crawl("http://golang.org/", 4, fetcher, results)
for i := 0; i < len(used); i++ {
fmt.Println(<-results)
}
}
我在main中使用“for i&lt; len(used)”行来确保只有在打印结果时才会打印结果中的值。我不能只使用
for i := range results
因为爬行函数很难使用“close(results)”,因为它是递归的,但是按照我的方式,我必须找到每次使用的变量的长度。
有更好的方法吗?
答案 0 :(得分:2)
要等待完成goroutine的集合,请使用sync.WaitGroup.
I believe you'll find the example in the official documentation very familiar..
http://golang.org/pkg/sync/#example_WaitGroup
Quoting:
var wg sync.WaitGroup
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
}
for _, url := range urls {
// Increment the WaitGroup counter.
wg.Add(1)
// Launch a goroutine to fetch the URL.
go func(url string) {
// Fetch the URL.
http.Get(url)
// Decrement the counter.
wg.Done()
}(url)
}
// Wait for all HTTP fetches to complete.
wg.Wait()
这将阻止所有工作完成。
如果您真的想在收集结果时逐步打印结果,最简单的方法是在提取器本身中执行此操作。