我有我正在刮的网址列表。我想要做的是将所有成功抓取的页面数据存储到一个通道中,当我完成时,将其转储到一个切片中。我不知道我会得到多少成功的提取,所以我不能指定一个固定的长度。我预计代码将达到wg.Wait()
,然后等到所有的wg.Done()
方法被调用,但我从未达到close(queue)
声明。寻找一个类似的答案,我碰到这个来得如此回答为什么我的代码在goroutine中运行wg.Wait()时工作正常?
https://stackoverflow.com/a/31573574/5721702
在这里笔者有类似的功能:
ports := make(chan string)
toScan := make(chan int)
var wg sync.WaitGroup
// make 100 workers for dialing
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for p := range toScan {
ports <- worker(*host, p)
}
}()
}
// close our receiving ports channel once all workers are done
go func() {
wg.Wait()
close(ports)
}()
只要我包裹着我的wg.Wait()
的够程内,close(queue)
达到:
urls := getListOfURLS()
activities := make([]Activity, 0, limit)
queue := make(chan Activity)
for i, activityURL := range urls {
wg.Add(1)
go func(i int, url string) {
defer wg.Done()
activity, err := extractDetail(url)
if err != nil {
log.Println(err)
return
}
queue <- activity
}(i, activityURL)
}
// calling it like this without the goroutine causes the execution to hang
// wg.Wait()
// close(queue)
// calling it like this successfully waits
go func() {
wg.Wait()
close(queue)
}()
for a := range queue {
// block channel until valid url is added to queue
// once all are added, close it
activities = append(activities, a)
}
为什么这些代码并没有达到close
如果我不使用股份公司oroutine for wg.Wait()
?我认为所有的defer wg.Done()
声明都会被调用,所以最终它会清除,因为它会到达wg.Wait()
。它是否与在我的频道中接收值有关?
你能展示整个代码吗? –
默认情况下,通道是无缓冲的,这意味着如果有相应的接收准备好接收发送的值,它们将只接受发送。因此,当您将活动发送到队列时,没有相应的接收,并且它被阻止。所有例程被阻止,最后wg.wait会挂起。有一个概念叫做缓冲通道,可以用来缓冲多个输入。通过https://gobyexample.com/channel-buffering去浏览 –