1 回答

TA貢獻1887條經(jīng)驗 獲得超5個贊
out在將每個結(jié)果寫入通道后,您需要關(guān)閉通道。最簡單的方法是當所有的工作 goroutine 都退出時,而最簡單的方法是使用sync.WaitGroup. (在 Go 中,通道和 goroutine 是非常密切相關(guān)的概念,因此 goroutine 管理是使用通道的一部分。)
在現(xiàn)有代碼中,您可以將其綁定到您的fetchUrl函數(shù)中:
var wg sync.WaitGroup
for url := range in {
two <- struct{}{}
wg.Add(1)
go func() {
defer wg.Done()
fetchWorker(url, two, out)
}()
}
wg.Wait()
close(out)
編寫代碼時遇到的另一個結(jié)構(gòu)性問題是,兩者都gen創(chuàng)建fetchUrl通道,運行所有應(yīng)該寫入通道的代碼,并僅在這些編寫者完成后返回通道;由于在函數(shù)返回之前無法從通道中讀取任何內(nèi)容,這將導(dǎo)致死鎖。您可以通過在頂層創(chuàng)建所有通道并將它們傳遞給生成器函數(shù)來解決此問題。
如果您想要兩個工作人員從同一個 URL 隊列中讀取,標準模式是啟動兩個從同一個通道讀取和寫入的 goroutine。例如,您可以重寫fetchWorker為
func fetchWorker(urls <-chan string, out chan<- string) {
for url := range urls {
res, err := http.Get("https://" + url)
if err != nil {
panic(err)
}
out <- fmt.Sprintf("[%d] %s\n", res.StatusCode, url)
}
}
在頂層,創(chuàng)建通道、創(chuàng)建工人、提供輸入并使用輸出。
func main() {
urls := make(chan string)
out := make(chan string)
// Launch a goroutine to feed data into urls, then
// close(urls), then stop
go gen(os.Args[1:], urls)
// Launch worker goroutines
workerCount := 2
var wg sync.WaitGroup
for i := 0; i < workerCount; i++ {
wg.Add(1)
go func() {
defer wg.Done()
fetchWorker(urls, out)
}()
}
// Launch a dedicated goroutine to close the channel
go func() {
wg.Wait()
close(out)
}()
// Read the results
for result := range(out) {
fmt.Println(result)
}
}
- 1 回答
- 0 關(guān)注
- 106 瀏覽
添加回答
舉報