我正在努力理解Go中的并发性。
package main
import "fmt"
func sendValues(myIntChannel chan int) {
for i := 0; i < 5; i++ {
myIntChannel <- i //sending value
}
}
func main() {
myIntChannel := make(chan int)
defer close(myIntChannel)
go sendValues(myIntChannel)
for value := range myIntChannel {
fmt.Println(value) //receiving value
}
}
上面的代码给出下面的输出:
0
1
2
3
4
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/Users/spikki/Desktop/GoLearning/go_channel.go:51 +0x10b
据我了解,延迟功能将在其周围的功能完成后执行。我无法解释。
如果我使用for循环从 channel 接收值,则其工作方式如下。
for i := 0; i < 5; i++ {
fmt.Println(<-myIntChannel) //receiving value
}
谁能帮我理解这个概念?
最佳答案
仅当从 channel 接收到所有值并且关闭 channel 后, channel 上的for ... range
才会终止。
在您的示例中,您希望使用延迟函数关闭 channel ,但是该操作仅在main()
返回时运行。但是main()
仅在循环结束时返回。这是导致死锁的原因。 for
循环等待 channel 关闭,关闭 channel 等待for循环结束。
当您使用循环从 channel 接收正好5个值时,它起作用了,因为启动的goroutines在其上发送了5个值。该循环不等待 channel 关闭,因此循环可以结束,main()
函数也可以结束。
这就是发送方应关闭 channel (而不是接收方)并立即解决问题的原因:
func sendValues(myIntChannel chan int) {
for i := 0; i < 5; i++ {
myIntChannel <- i //sending value
}
close(myIntChannel)
}
func main() {
myIntChannel := make(chan int)
go sendValues(myIntChannel)
for value := range myIntChannel {
fmt.Println(value) //receiving value
}
}
输出(在Go Playground上尝试):
0
1
2
3
4
关于for-loop - 为什么不执行延迟功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60788950/