使用 goroutine 和闭包从并发函数读取并发错误
Reading from a concurrent function via channel using goroutine and a closure giving error
我有一个正在写入通道的函数(不是闭包)。我正在从 goroutine 中调用该函数 as
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()
}
现在我正在尝试使用另一个 goroutine 从该频道读取数据。
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
如果我给出 wgread.Add(2),它会打印上面的 DONE 和 false 3 次。
尽管我将等待组增量递增 1,但为什么给出负等待组计数器错误?使用另一个并发函数或闭包从 goroutine 读取的最佳方法是什么?
break
不会中断外部 for
循环。
要引用外部循环,您可以使用这样的标签:
Loop:
for {
select {
case ...:
break Loop
}
}
也有助于编码风格,
你应该练习使用 gofmt 来格式化你的代码。例如,它将 for ; ; { ... }
替换为更清洁的 for { ... }
.
break语句跳出最内层的case,for或switch语句。在 somechan
上接收的函数在循环中自旋,当通道关闭时递减等待组。像这样写代码:
wgread.Add(1)
go func() {
defer wgread.Done()
for chanoutput := range somechan {
fmt.Println(string(*chanoutput))
}
fmt.Println("DONE")
}()
wgread.Wait()
如果接收代码如题中所写,则接收goroutine可以消除。将 wgread.Add(1)
到 wgread.Wait()
的代码替换为
for chanoutput := range somechan {
fmt.Println(string(*chanoutput))
}
我有一个正在写入通道的函数(不是闭包)。我正在从 goroutine 中调用该函数 as
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()
}
现在我正在尝试使用另一个 goroutine 从该频道读取数据。
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
如果我给出 wgread.Add(2),它会打印上面的 DONE 和 false 3 次。
尽管我将等待组增量递增 1,但为什么给出负等待组计数器错误?使用另一个并发函数或闭包从 goroutine 读取的最佳方法是什么?
break
不会中断外部 for
循环。
要引用外部循环,您可以使用这样的标签:
Loop:
for {
select {
case ...:
break Loop
}
}
也有助于编码风格,
你应该练习使用 gofmt 来格式化你的代码。例如,它将 for ; ; { ... }
替换为更清洁的 for { ... }
.
break语句跳出最内层的case,for或switch语句。在 somechan
上接收的函数在循环中自旋,当通道关闭时递减等待组。像这样写代码:
wgread.Add(1)
go func() {
defer wgread.Done()
for chanoutput := range somechan {
fmt.Println(string(*chanoutput))
}
fmt.Println("DONE")
}()
wgread.Wait()
如果接收代码如题中所写,则接收goroutine可以消除。将 wgread.Add(1)
到 wgread.Wait()
的代码替换为
for chanoutput := range somechan {
fmt.Println(string(*chanoutput))
}