Go Routines 有时有效,有时会出现关闭通道错误
Go Routines sometimes work, sometimes gives close channel error
我是 Go 新手,正在尝试了解并发模式。当我 运行 下面的代码时,我有时会得到预期的结果(从 0 到 9999 的完整数字数组)。其他时候我只是收到一条显示时间的 "That's it" 消息。有时我只会收到 "Sending on closed channel" 错误。这里可能出了什么问题?
package main
import (
"fmt"
"time"
"sync"
)
func JobsDispatcher(in chan int, data []int){
for _, value := range data{
in<-value
}
close(in)
}
func Worker(in chan int, out chan int, wg *sync.WaitGroup){
wg.Add(1)
for{
inMsg, ok := <-in
if !ok{
wg.Done()
return
}
out <- inMsg
}
}
func PrintInt(out chan int){
for {
outMsg, ok := <-out
if !ok{
fmt.Println("")
fmt.Println("That's it")
return
}
fmt.Println(outMsg)
}
}
func ParallelPrint(data []int){
var wg sync.WaitGroup
in := make(chan int)
out := make(chan int)
parallelStartTime := time.Now()
go JobsDispatcher(in, data)
for i:=0;i<5;i++{
go Worker(in,out,&wg)
}
go func(){
wg.Wait()
close(out)
}()
PrintInt(out)
fmt.Println(time.Since(parallelStartTime))
}
func main(){
data := make([]int,0)
for i:=0;i<10000;i++{
data = append(data, i)
}
ParallelPrint(data)
}
这个很简单。这就是为什么你从不在 goroutine 中使用 WaitGroup 的 Add 。始终在启动 goroutine 之前调用它。
问题是你堆积了一堆 goroutine,然后立即调用 Wait。 Go 不承诺 运行 你的 goroutines 在任何特定时间,就像 POSIX 或 Windows 线程不是 gua运行teed.
所以,在这种情况下,你给了调度器一堆 goroutines 到 运行 以后,但它决定先完成你的代码。所以它 运行 wg.Wait()
和 close(out)
在做 wg.Add()
.
之前
您想在 wg.Add
goroutine 之外调用 - 即:
for i:=0;i<5;i++{
wg.Add(1) // Here, not inside Worker()
go Worker(in,out,&wg)
}
否则,它可以添加所有工人,在任何工人呼叫wg.Add
之前点击wg.Wait
,这将立即return,然后关闭通道。
我是 Go 新手,正在尝试了解并发模式。当我 运行 下面的代码时,我有时会得到预期的结果(从 0 到 9999 的完整数字数组)。其他时候我只是收到一条显示时间的 "That's it" 消息。有时我只会收到 "Sending on closed channel" 错误。这里可能出了什么问题?
package main
import (
"fmt"
"time"
"sync"
)
func JobsDispatcher(in chan int, data []int){
for _, value := range data{
in<-value
}
close(in)
}
func Worker(in chan int, out chan int, wg *sync.WaitGroup){
wg.Add(1)
for{
inMsg, ok := <-in
if !ok{
wg.Done()
return
}
out <- inMsg
}
}
func PrintInt(out chan int){
for {
outMsg, ok := <-out
if !ok{
fmt.Println("")
fmt.Println("That's it")
return
}
fmt.Println(outMsg)
}
}
func ParallelPrint(data []int){
var wg sync.WaitGroup
in := make(chan int)
out := make(chan int)
parallelStartTime := time.Now()
go JobsDispatcher(in, data)
for i:=0;i<5;i++{
go Worker(in,out,&wg)
}
go func(){
wg.Wait()
close(out)
}()
PrintInt(out)
fmt.Println(time.Since(parallelStartTime))
}
func main(){
data := make([]int,0)
for i:=0;i<10000;i++{
data = append(data, i)
}
ParallelPrint(data)
}
这个很简单。这就是为什么你从不在 goroutine 中使用 WaitGroup 的 Add 。始终在启动 goroutine 之前调用它。
问题是你堆积了一堆 goroutine,然后立即调用 Wait。 Go 不承诺 运行 你的 goroutines 在任何特定时间,就像 POSIX 或 Windows 线程不是 gua运行teed.
所以,在这种情况下,你给了调度器一堆 goroutines 到 运行 以后,但它决定先完成你的代码。所以它 运行 wg.Wait()
和 close(out)
在做 wg.Add()
.
您想在 wg.Add
goroutine 之外调用 - 即:
for i:=0;i<5;i++{
wg.Add(1) // Here, not inside Worker()
go Worker(in,out,&wg)
}
否则,它可以添加所有工人,在任何工人呼叫wg.Add
之前点击wg.Wait
,这将立即return,然后关闭通道。