1 回答
TA贡献1858条经验 获得超8个赞
好的,我们开始吧。首先,请注意您的代码中存在一些问题。然后修复它们。
正如Adrian所说,从已经关闭或没有元素的通道中读取。在您的工作人员功能中,您正在这样做。当您在另一个工作人员关闭输入通道后从输入通道读取元素时,就会发生这种情况。
func worker(input chan int, output chan<- int) {
defer close(input)
...
for {
element, more := <-input
...
}
}
那么,为什么在所有工作人员完成后不关闭输入通道?
在解决了输入通道的问题后,当您尝试从输出通道读取时,会出现另一个问题。此外,您不会在输出通道上发送任何内容。如果您不需要该频道,那么为什么要使用该频道。而且这个输出通道是无缓冲的(大小为0的通道和发送接收应该同时,否则会出现死锁情况)。看,从这里和这里缓冲与无缓冲。也许网络上有更多有用的文档。感谢我的朋友Nightfury1204从他的这篇文章中获得了关于缓冲与非缓冲频道的第一个链接。
outputChannel := make(chan int) // unbuffered, no size is defined
...
for elem := range outputChannel {
fmt.Println("Output: ", elem)
}
所以,如果你想向输出通道发送一些东西,那么逻辑是你自己的。例如,您可以在工作人员中完成输入通道处理后发送一些内容。在这种情况下,将您的输出通道声明为长度为 4 的缓冲通道(因为您正在运行 4 个工作人员)。完成所有工作人员后,关闭您的输出通道,然后阅读。
outputChannel := make(chan int, 4) // buffered
...
// after finishing all your workers
close(outputChannel)
for elem := range outputChannel {
fmt.Println("Output: ", elem)
}
需要注意的是,使用sync.WaitGroupfrom "sync"package 来等待一组 goroutine 完成。
请参见下面的示例:https: //play.golang.org/p/WAqwyR0ggNN
import "fmt"
import "sync"
func main() {
inputChannel := make(chan int, 1)
outputChannel := make(chan int, 4)
var wg sync.WaitGroup
wg.Add(4)
inputChannel <- 100
numWorkers := 4
for i := 0; i < numWorkers; i++ {
go func() {
defer wg.Done()
for {
select {
case element := <-inputChannel:
fmt.Println("Input: ", element)
element--
if element != 0 {
inputChannel <- element
}
default:
outputChannel<-0
fmt.Println("All Jobs Processed", len(outputChannel))
return
}
}
}()
}
wg.Wait()
close(inputChannel)
close(outputChannel)
for elem := range outputChannel {
fmt.Println("Output: ", elem)
}
}
- 1 回答
- 0 关注
- 175 浏览
添加回答
举报
