我有一个缓冲通道,有意限制为2个元素。当我在不读取任何内容的情况下向该通道写入更多元素时,就会出现预期的死锁。但是,如果我使用goroutine向我的频道进行写操作,问题就消失了。为什么?
// Function to process messages in an array. We stop processing once we
// encounter the string 'stop' even if there are other messages
func processCmd(s []string, c chan int) {
msgCount := 0
for index, v := range s {
if index == len(s)-1 && v == "stop" {
// If we've reached the last element and the message is "stop", don't count it
break
} else if v == "stop" {
c <- msgCount // Send msgCount to the channel
continue
} else {
msgCount++
}
}
c <- msgCount // Send msgCount to the channel
close(c)
}
func main() {
s := []string{"message a", "message b", "message c", "stop", "message d", "stop", "message e"}
c := make(chan int, 2)
processCmd(s, c)
//go processCmd(s, c) // doesn't have an issue with buffer length
for v := range c {
fmt.Println(v)
}
}
最佳答案
内联运行processCmd
时(如代码所示),该通道没有任何内容可接收。一旦添加了两个元素,processCmd
将只等到有空间添加更多元素。如您所说,这按预期工作。
在goroutine中运行processCmd
时,main()
启动goroutine并进入for v := range c
循环。这将消耗c
中的项目,直到关闭通道。一旦v := range c
消耗了第一个元素,processCmd
便可以自由地向通道添加更多数据,从而对其进行解锁。
这将一直持续到processCmd
关闭通道为止,此时for循环将终止,程序也将终止。
注意:为了获得可见性,请不要忘记添加go
标签。观看goroutine
标签的人并不多。