Go Chan和WaitGroup的问题

Go Chan和WaitGroup的问题,go,Go,虽然我看到过类似的问题,但在SO上找到的答案对我都没有帮助,但我希望一个有着鹰眼的善良灵魂能帮助我找到问题所在。我知道这不是goroutines的最佳用途,但我想把它作为一种练习,但显然失败了 我的代码 主程序包 进口( “fmt” “排序” “同步” ) func main(){ X:=[]int{1,2,3,4,0} Y:=[]int{2,3,6,8,4} 溶液:=溶液(X,Y) fmt.Println(解决方案) } //溶液 func解(X[]int,Y[]int)int{ 尺寸:=透镜

虽然我看到过类似的问题,但在SO上找到的答案对我都没有帮助,但我希望一个有着鹰眼的善良灵魂能帮助我找到问题所在。我知道这不是goroutines的最佳用途,但我想把它作为一种练习,但显然失败了

我的代码

主程序包
进口(
“fmt”
“排序”
“同步”
)
func main(){
X:=[]int{1,2,3,4,0}
Y:=[]int{2,3,6,8,4}
溶液:=溶液(X,Y)
fmt.Println(解决方案)
}
//溶液
func解(X[]int,Y[]int)int{
尺寸:=透镜(X)
结果chan:=make(chan int)
结果:=make(映射[int]int)
ParseDivision(大小、X、Y、结果)
对于val:=范围结果chan{
结果[val]=结果[val]+1
}
关闭(resultChan)
返回FindCreatest(结果)
}
//分
func Divide(a int,b int,resultChan chan需要注意的一些事情:

  • 写入通道的go例程通常应关闭通道
  • 从上面开始,“读卡器”go例程应等待通道关闭(通过范围et.c)-即,它不必关闭其读取的通道
  • 由于您的结果通道是无缓冲的(缓冲区大小为0),主go例程将在工作人员尝试写入时阻塞,并且主go例程尚未(尚未)从结果通道读取数据(因为池管理器go例程必须完成才能发生此情况-死锁!)。解决方案:
    • 确保工作池go例程独立于主(读卡器)go例程运行

三行修复:

最明显的部分是您没有
关闭(resultChan)
直到你读完它之后,在主goroutine中,你将永远看不到频道的尽头。正如我键入此内容时发布的答案所指出的,你还需要剥离整个编剧/侍者。谢谢@colm.anseo确实,我不得不作为goroutine运行
ParseDivision
,同时不得不关闭频道。我只是有一个额外的问题:所以我看到的大多数例子都是按照你刚才告诉我的做的(例如:让作者goroutine关闭频道-在我的例子中,
划分
).但是,在我的例子中,Divide在循环中运行,在那里关闭它会导致在以后的运行中尝试写入闭合通道时出错。使用defer将其移动到
ParseDivision
(以前尝试过,但当它不作为goroutine运行时失败)。为什么?在我看来,在范围之前关闭main也是一样的。@AndreiDascalu关闭通道是工作池中最微妙的部分-您必须保证通道关闭后不会有工作人员写入通道。因此,您正确地使用了
sync.WaitGroup
来确保所有工作都已完成。然后在
wg.Wait()之后
关闭结果频道是安全的。