我有一个写通道的函数(不是闭包)。我从程序中调用该函数作为
var wg sync.WaitGroup
wg.Add(1)
go DoStuff(somechan, &wg)
在DoStuff里面,我有类似
的内容for ; ; {
if err == io.EOF {
fmt.Println(err)
close(somechan)
fmt.Println("Closed channel")
break
} else if err != nil {
panic(err)
}
somechan <- Somefunc()
}
现在我正在尝试使用另一个程序从该通道读取。
wgread.Add(1)
go func() {
for ; ; {
select {
case chanoutput, ok := <-somechan:
if ok == true {
fmt.Println(string(*chanoutput))
} else {
fmt.Println("DONE")
fmt.Println(ok)
wgread.Done()
break
}
}
}
}()
wgread.Wait()
然而,当运行时,我得到
panic: sync: negative WaitGroup counter
打印后
DONE
false
DONE
false
如果我输入wgrad . add(2),它将打印上述DONE和false 3次。
为什么给一个负的等待组计数器错误,虽然我增加了等待组增量1?使用另一个并发函数或闭包从程序中读取数据的最佳方法是什么?
break语句从最内部的for或switch语句中跳出来。当通道关闭时,在somechan
上接收的函数在循环中旋转,减少等待组。像这样编写代码:
wgread.Add(1)
go func() {
defer wgread.Done()
for chanoutput := range somechan {
fmt.Println(string(*chanoutput))
}
fmt.Println("DONE")
}()
wgread.Wait()
如果接收代码与问题中所写的一样,则可以消除接收例程。将wgread.Add(1)
到wgread.Wait()
的代码替换为
for chanoutput := range somechan {
fmt.Println(string(*chanoutput))
}
break
不打破外部for
循环。要引用外部循环,可以使用这样的标签:
Loop:
for {
select {
case ...:
break Loop
}
}
也是为了帮助编码风格,您应该练习使用gofmt来格式化代码。例如,它将用更简洁的for { ... }
替换for ; ; { ... }
。