这是我之前帖子的后续: http://stackoverflow.com/questions/34736825/goroutine-exit-status-2-what-does-it-mean-why-is-it-happening?noredirect=1#comment57238789_34736825在阅读了 SO 内外的多个主题和文章后,我仍然无法确定应该关闭渠道的位置。该程序将打开一个文件列表,为每个输入文件创建一个输出文件(具有相同的名称),访问每个输入文件中的所有 url 并从中获取所有 href 链接 - 保存到相应的输出文件中。但是,我收到以下错误: http://play.golang.org/p/8X-1rM3aXClinkgetter 和 getHref 函数主要用于处理。Head 和 tail 作为单独的 goroutine 运行,而 worker 进行处理。 package main import ( "bufio" "bytes" "fmt" "golang.org/x/net/html" "io" "io/ioutil" "log" "net/http" "os" "path/filepath" "regexp" "sync" ) type Work struct { Link string Filename string } type Output struct { Href string Filename string } func getHref(t html.Token) (href string, ok bool) { // Iterate over all of the Token's attributes until we find an "href" for _, a := range t.Attr { if a.Key == "href" { href = a.Val ok = true } } return } func linkGetter(out chan<- Output, r io.Reader, filename string) { z := html.NewTokenizer(r) for { tt := z.Next() switch { case tt == html.ErrorToken: return case tt == html.StartTagToken: t := z.Token() isAnchor := t.Data == "a" if !isAnchor { continue } // Extract the href value, if there is one url, ok := getHref(t) if !ok { continue } out <- Output{url, filename} } } 通道关闭的方式有什么问题?
1 回答
qq_笑_17
TA贡献1818条经验 获得超7个赞
在这里,您并没有真正关注您的管道设计。你必须问自己“X 部分什么时候完成?完成后会发生什么?完成后会发生什么?” 对于管道的每个部分。
您启动head
,tail
以及worker
以射程超过通道。这些函数成功返回的唯一方法是关闭这些通道。
把它画出来你需要。
head(in)
馈入in
worker(out, in, &wg)
覆盖in
,输入out
,并告诉您它已完成,wg
一旦in
关闭tail(out)
范围超过out
那么你需要做什么:
确保处理所有输入?
确保所有 goroutine 都返回?
像这样:
您需要关闭
in
从head
一旦处理完所有的文件。这将导致在处理
worker
它可以从中获取的所有项目后实际返回in
,导致wg.Wait()
返回现在可以安全关闭,
out
因为没有任何东西进入它,这将导致tail
最终返回。
但是您可能需要另一个sync.WaitGroup
与tail
此特定设计相关的程序,因为整个程序将在wg.Wait()
返回时立即退出,因此可能无法完成tail
正在执行的所有工作。见这里。具体来说:
程序执行首先初始化主包,然后调用函数 main。当该函数调用返回时,程序退出。它不会等待其他(非主)goroutine 完成。
您可能还想使用此处引用的缓冲通道来帮助避免在 goroutine 之间进行过多的切换执行。对于您当前的设计,您在上下文切换上浪费了大量时间。
- 1 回答
- 0 关注
- 113 浏览
添加回答
举报
0/150
提交
取消