我正在学习GO。在学习了一些基础知识之后,我一直在尝试编写一个小程序,该程序使用goroutines同时下载网页( slice 中的网址)到不同的文件。这是我写的一些代码:
func downloadFromUrl(url string) {
tokens := strings.Split(url, "/")
fileName := tokens[len(tokens)-1]
// I took out the bit that download the file for testing.
fmt.Println("Downloading", url, "to", fileName)
}
我评论了实际下载页面进行测试的部分。在我的主要职能中,我正在这样做:
func main() {
urls := []string{"http://www.google.com", "http://www.yahoo.com", "http://www.google.com"}
for _, url := range urls {
fmt.Println(url);
go downloadFromUrl(url);
}
}
问题是,当我使用表达式
go downloadFromUrl(url);
时,函数downloadFromUrl无法运行。但是,如果我仅在循环中使用downloadFromUrl(url)
,则效果很好。我究竟做错了什么?我必须在例程中使用channel吗? 最佳答案
问题是在goroutine返回之前是主导出,最简单的解决方案是使用 sync.WaitGroup
。
func main() {
urls := []string{"http://www.google.com", "http://www.yahoo.com", "http://www.google.com"}
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
log.Println(url)
go downloadFromUrl(url, &wg)
}
wg.Wait()
}
func downloadFromUrl(url string, wg *sync.WaitGroup) {
defer wg.Done()
....
}