golang:如何在所有 goroutine 完成后关闭通道?

我想在 Go 中编写一个简单的网络爬虫:

  • 从 URL 中获取带有模式的所有 href

  • 提取一些特定的字段

  • 并写入 CSV 文件

这是我的代码:

问题是在所有 goroutine 完成后通道没有关闭,我必须按control+C才能返回我的 shell 提示:


2016/03/02 09:34:05 Fetching URL ...

2016/03/02 09:34:05 Fetching URL ...

2016/03/02 09:34:05 Fetching URL ...

^Csignal: interrupt

通过阅读本文,我将getDocfunc 中的最后一行更改为:


go func() {

    wg.Wait()

    close(c)

}()

现在我可以在运行时恢复我的 shell 提示,但是在所有 goroutine 完成之前通道已关闭,并且没有任何内容写入 CSV 文件。


我哪里做错了?


千巷猫影
浏览 139回答 2
2回答

一只萌萌小番薯

对我来说,它看起来不像是从您的频道读取,并且因为它是一个同步频道(您从未在其上声明长度),如果它接收到一个值,它就会阻塞。所以你需要从你的cbyvalue <- c或你的 fetch 函数中读取c <- *e这导致你sync.WaitGroup永远wg.Done()不会减少计数器,这永远不会导致wg.Wait()停止阻塞,这导致你close(c)永远不会被调用

皈依舞

我的原始代码是这样的:e_hrefs := findHrefs(u)w := csv.NewWriter(file)for e_href, name := range e_hrefs {&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go fetch(parsedUrl.Scheme+"://"+parsedUrl.Host+e_href, name, &wg, c)&nbsp; &nbsp; e := <-c&nbsp; &nbsp; w.Write([]string{name, "'" + e.tax_code, e.group, e.capital})&nbsp; &nbsp; w.Flush()}wg.Wait()你可以看到,这不是并发。我刚刚通过使用range子句迭代通道来修复:e_hrefs := findHrefs(u)for e_href, name := range e_hrefs {&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go fetch(parsedUrl.Scheme+"://"+parsedUrl.Host+e_href, name, &wg, c)}go func() {&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; close(c)}()w := csv.NewWriter(file)for e := range c {&nbsp; &nbsp; w.Write([]string{e.name, "'" + e.tax_code, e.group, e.capital})&nbsp; &nbsp; w.Flush()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java