Goroutine没有按预期运行
我仍在学习Go,并在做链接的网络爬虫练习。我实现的主要部分如下。其他部分保持不变,可以在链接中找到 //爬网使用抓取器进行递归爬网 //以url开头的页面,最大深度。 func Crawlurl字符串,深度int,获取程序{ //TODO:并行获取URL。 //TODO:不要获取同一URL两次。 //此实现既不执行以下操作,也不执行以下操作:Goroutine没有按预期运行,go,Go,我仍在学习Go,并在做链接的网络爬虫练习。我实现的主要部分如下。其他部分保持不变,可以在链接中找到 //爬网使用抓取器进行递归爬网 //以url开头的页面,最大深度。 func Crawlurl字符串,深度int,获取程序{ //TODO:并行获取URL。 //TODO:不要获取同一URL两次。 //此实现既不执行以下操作,也不执行以下操作: 如果深度您的程序很可能在爬网程序完成其工作之前退出。一种方法是爬网程序有一个等待组,等待其所有子爬网程序完成。例如 import "sync" // C
如果深度您的程序很可能在爬网程序完成其工作之前退出。一种方法是爬网程序有一个等待组,等待其所有子爬网程序完成。例如
import "sync"
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, *wg sync.WaitGroup) {
defer func() {
// If the crawler was given a wait group, signal that it's finished
if wg != nil {
wg.Done()
}
}()
if depth <= 0 {
return
}
_, urls, err := fetcher.Fetch(url)
cache.Set(url)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("found: %s %q\n", url, body)
var crawlers sync.WaitGroup
for _, u := range urls {
if cache.Get(u) == false {
fmt.Println("Next:", u)
crawlers.Add(1)
go Crawl(u, depth-1, fetcher, &crawlers)
}
}
crawlers.Wait() // Waits for its sub-crawlers to finish
return
}
func main() {
// The root does not need a WaitGroup
Crawl("http://example.com/index.html", 4, nil)
}
您是否在爬网功能中添加了go Crawl?最有可能的是,您的程序在爬网程序完成工作之前退出。查看@Niwatori您检查的答案显然是错误的:如果您像在代码中那样添加GoRoutine,则有竞争条件,这不太难修复,但需要一些修改effort@zerkms你能告诉我埃拉博拉吗有一点?我猜变量u导致了竞争条件,但不是很确定。在非并发代码中使用WaitGroup有什么意义?如果删除它,什么都不会改变。我假设它应该是循环中的go-Crawlu、depth-1、fetcher和crawlers,但它确实解决了问题。谢谢!@Niwatori如果您添加go-there,那么这段代码就可以了很容易出现竞态条件。所以这并不能解决问题。@Tristian:现在,在您修改代码之后-在并发的wg.Add和wg.Wait调用周围很容易出现竞态条件。我错了,这里没有竞态条件,我道歉。
found: https://golang.org/ "The Go Programming Language"
Next: https://golang.org/pkg/
Next: https://golang.org/cmd/
import "sync"
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, *wg sync.WaitGroup) {
defer func() {
// If the crawler was given a wait group, signal that it's finished
if wg != nil {
wg.Done()
}
}()
if depth <= 0 {
return
}
_, urls, err := fetcher.Fetch(url)
cache.Set(url)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("found: %s %q\n", url, body)
var crawlers sync.WaitGroup
for _, u := range urls {
if cache.Get(u) == false {
fmt.Println("Next:", u)
crawlers.Add(1)
go Crawl(u, depth-1, fetcher, &crawlers)
}
}
crawlers.Wait() // Waits for its sub-crawlers to finish
return
}
func main() {
// The root does not need a WaitGroup
Crawl("http://example.com/index.html", 4, nil)
}