等待所有 goroutine 完成并合并结果

问题描述

我很难理解 goroutines、channels 和所有同步的东西。我相信我理解这些概念,但我缺少几行来连接我拥有的所有信息。此外,大多数示例感觉太简单了,所以我无法正确掌握实际发生的情况。

我正在为网站编写一个简单的分析工具。其中一项功能是检查本网站上的所有链接是否均可访问。显然,每个网站上都有很多链接,所以它看起来是一个很好的 goroutines 候选者。问题是,在调度完所有 goroutine 之后,我需要取回所有结果,以便一次性将它们呈现给用户。

到目前为止我所拥有的是:

func links(u *url.URL,d *goquery.Document) (links []models.Link) {
    wg := sync.WaitGroup{}

    d.Find("a[href]").Each(func(index int,item *goquery.Selection) {
        go func() {
            wg.Add(1)
            href,_ := item.Attr("href")
            url,_ := url.Parse(href)
            var internal bool

            if url.Host == "" {
                url.Scheme = u.Scheme
                url.Host = u.Host
            }

            links = append(links,models.Link{
                URL:       url,Reachable: Reachable(url.String()),})

            wg.Done()
        }()
    })

    wg.Wait()

    return
}

func Reachable(u string) bool {
    res,err := http.Head(u)
    if err != nil {
        return false
    }

    return res.StatusCode == 200
}

我的代码似乎可以工作,但我觉得我错过了一些东西(或者至少它可能会更好)。我有几个顾虑/问题:

  1. 如果网站将包含 1000 个链接,我会生成 1000 个 goroutine,我相信它不会那么聪明。可能我需要一个工作池或类似的东西,对吧?
  2. 是否可以仅在此示例中使用频道?我不知道 goquery 会找到多少个链接,因此我无法轻松 range 超过发送到频道的元素。此外,我无法轻松地向另一个频道发送一些 done 消息,因为我不知道此 Each 何时结束。此频道上的每个 for range 都处于阻塞状态,因此应用正在恢复同步。
  3. 我相信这在应用程序中很常见,您开始迭代某些东西,并且希望在每次迭代中做一些异步工作,并在结束时收集所有结果。我无法理解这个概念。我想不出如何处理这种情况。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)