我有我正在刮的網址列表。我想要做的是將所有成功抓取的頁面數據存儲到一個通道中,當我完成時,將其轉儲到一個切片中。我不知道我會得到多少成功的提取,所以我不能指定一個固定的長度。我預計代碼將達到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去瀏覽 –