如何实现等待goroutines执行完成后退出main函数?

之前爬虫用python写总是出问题,于是换成了Go来写,大致内容如下:

    for ;next_url != first_url; {
        count += 1
        strBody = getContent(next_url)
        re = regexp.MustCompile("photos-view-id-\\d+.html")
        next_url =  getNextUrl(strBody)
        re = regexp.MustCompile("http://xxxx/data/[^\"]+")
        pic_url = re.FindAllString(strBody, 2)[1]
        filename = fmt.Sprintf("%03d.jpg", count)
        go downloadFromUrl(pic_url, save_path + filename)
    }

但是这样会有一个问题就是我的downloadFromUrl还没执行完成时,程序已经退出了,导致最后几个文件未下载成功。有什么方法可以等待操作完成之后退出程序的么?

阅读 15.8k
2 个回答

参考 @方泽图 的回复,实现方式如下:

var wg sync.WaitGroup
...
    for ;next_url != first_url; {
        ....
        filename = fmt.Sprintf("%03d.jpg", count)
        wg.Add(1)
        go func(pic_url string, saveto string) {
            defer wg.Done()
            downloadFromUrl(pic_url, saveto)
        }(pic_url, saveto)
    }
    wg.Wait()

在《Go语言编程》这本书中介绍过。

使用Channel通信来解决,goruntime没有执行完,main就退出的问题。简单示例如下:

package main

import "fmt"

func download(url string, ch chan int) {
    fmt.Println(url)
    ch <- 1
}

func main() {
    urls := []string{
        "http://www.a.com/1.gzip",
        "http://www.a.com/2.gzip",
        "http://www.a.com/3.gzip",
        "http://www.a.com/4.gzip",
    }
    ch := make(chan int, 4)
    for _, v := range urls {
        go download(v, ch)
    }
    for i := 0; i < len(urls); i++ {
        <-ch
    }
    fmt.Println("over")
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏