关于程序:我正在尝试通过我自己的一流类型实现管道intJob
模式。聚合管道的主要功能正是ExecutePipeline2
它导致了问题。
为什么我总是遇到死锁?对我来说,我似乎在每个 goroutine 之后都关闭了所有读者使用的通道。另外,创建带缓冲区的通道也无济于事,所以我完全没有主意了,非常感谢你的帮助。
重要提示main
:当基础(提到的功能)保持不变时,我无法更改功能并仅从其他功能实现这个想法。
type intJob func(a, b chan int)
func ExecutePipeline2(jobs ...intJob) {
outs := make([]chan int, len(jobs)+1)
wg := sync.WaitGroup{}
for i := 0; i < len(outs); i++ {
outs[i] = make(chan int)
}
for i, job := range jobs {
job := job
in, out := outs[i], outs[i+1]
i := i
wg.Add(1)
go func() {
job(in, out)
fmt.Printf("job %d closed\n", i)
close(out)
wg.Done()
}()
}
wg.Wait()
}
func pipe(_, b chan int) {
for i := 0; i < 5; i++ {
b <- i
}
}
func main() {
inputData := []int{0, 1, 1, 2, 3, 5, 8}
hashSignJobs := []intJob{
intJob(func(in, out chan int) {
for _, fibNum := range inputData {
out <- fibNum
}
}),
intJob(pipe),
intJob(func(in, out chan int) {
for val := range in {
fmt.Println(val)
}
}),
}
ExecutePipeline2(hashSignJobs...)
}
我认为关键问题在于你的第二条管道
pipe()
,它不是从前一条管道的输出中读取,而是开始循环生成数字。应该按如下方式编写,以便从in
as中读取您也可以将执行函数重写为如下所示的内容。完整示例位于https://go.dev/play/p/K_-UFzz0zt5
此代码片段中创建的第一个“输出”(1 索引)通道
不使用作为“生产者”,并且在第一次迭代之后
intJob
和在第二次迭代中第一次intJob
出现死锁(因为chan
已满):PLAYGROUND