为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

千巷猫影 2021-12-20 10:51:44
我想在 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 文件。我哪里做错了?
查看完整描述

2 回答

?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

对我来说,它看起来不像是从您的频道读取,并且因为它是一个同步频道(您从未在其上声明长度),如果它接收到一个值,它就会阻塞。所以你需要从你的cbyvalue <- c或你的 fetch 函数中读取c <- *e

这导致你sync.WaitGroup永远wg.Done()不会减少计数器,这永远不会导致wg.Wait()停止阻塞,这导致你close(c)永远不会被调用


查看完整回答
反对 回复 2021-12-20
?
皈依舞

TA贡献1851条经验 获得超3个赞

我的原始代码是这样的:


e_hrefs := findHrefs(u)

w := csv.NewWriter(file)

for e_href, name := range e_hrefs {

    wg.Add(1)

    go fetch(parsedUrl.Scheme+"://"+parsedUrl.Host+e_href, name, &wg, c)

    e := <-c

    w.Write([]string{name, "'" + e.tax_code, e.group, e.capital})

    w.Flush()

}

wg.Wait()

你可以看到,这不是并发。


我刚刚通过使用range子句迭代通道来修复:


e_hrefs := findHrefs(u)

for e_href, name := range e_hrefs {

    wg.Add(1)

    go fetch(parsedUrl.Scheme+"://"+parsedUrl.Host+e_href, name, &wg, c)

}

go func() {

    wg.Wait()

    close(c)

}()


w := csv.NewWriter(file)

for e := range c {

    w.Write([]string{e.name, "'" + e.tax_code, e.group, e.capital})

    w.Flush()

}


查看完整回答
反对 回复 2021-12-20
  • 2 回答
  • 0 关注
  • 138 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信