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

Golang 卡在 WaitGroup

Golang 卡在 WaitGroup

Go
小怪兽爱吃肉 2021-11-01 10:38:57
我被困在自己的等待循环中,不确定为什么。该函数采用输入和输出通道,然后采用通道中的每个项目,为内容执行 http.GET 并从 html 中提取标签。获取和抓取的过程在一个 go 例程中,我已经设置了一个等待组 (innerWait) 以确保在关闭输出通道之前我已经处理了所有内容。   func (fp FeedProducer) getTitles(in <-chan feeds.Item,    out chan<- feeds.Item,    wg *sync.WaitGroup) {    defer wg.Done()    var innerWait sync.WaitGroup    for item := range in {        log.Infof(fp.c, "Incrementing inner WaitGroup.")        innerWait.Add(1)        go func(item feeds.Item) {            defer innerWait.Done()            defer log.Infof(fp.c, "Decriment inner wait group by defer.")            client := urlfetch.Client(fp.c)            resp, err := client.Get(item.Link.Href)            log.Infof(fp.c, "Getting title for: %v", item.Link.Href)            if err != nil {                log.Errorf(fp.c, "Error retriving page. %v", err.Error())                return            }            if strings.ToLower(resp.Header.Get("Content-Type")) == "text/html; charset=utf-8" {                title := fp.scrapeTitle(resp)                item.Title = title            } else {                log.Errorf(fp.c, "Wrong content type.  Received: %v from %v", resp.Header.Get("Content-Type"), item.Link.Href)            }            out <- item        }(item)    }    log.Infof(fp.c, "Waiting for title pull wait group.")    innerWait.Wait()    log.Infof(fp.c, "Done waiting for title pull.")    close(out)}func (fp FeedProducer) scrapeTitle(request *http.Response) string {    defer request.Body.Close()    tokenizer := html.NewTokenizer(request.Body)    var titleIsNext bool    for {        token := tokenizer.Next()        switch {        case token == html.ErrorToken:            log.Infof(fp.c, "Hit the end of the doc without finding title.")            return ""        case token == html.StartTagToken:            tag := tokenizer.Token()            isTitle := tag.Data == "title"我可以看到我正在根据日志使用 innerWait.Wait() 命令,这也告诉我入站通道已在管道的另一侧关闭。匿名函数中的 defer 语句似乎没有被调用,因为我在任何地方都看不到延迟日志语句。但是我终生无法解释为什么该块中的所有代码似乎都在执行。帮助表示赞赏。
查看完整描述

1 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超14个赞

goroutines 被困out在这一行:

        out <- item

解决方法是启动一个 goroutine 来接收out.

调试此类问题的一个好方法是通过向进程发送 SIGQUIT 来转储 goroutine 堆栈。


查看完整回答
反对 回复 2021-11-01
  • 1 回答
  • 0 关注
  • 153 浏览
慕课专栏
更多

添加回答

举报

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