for-loop - 为什么延迟函数不执行?
问题描述
我正在努力理解 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
据我了解, defer 函数将在其周边函数完成后执行。我无法解释它。
如果我使用 for 循环从通道接收值,它的工作方式如下。
for i := 0; i < 5; i++ {
fmt.Println(<-myIntChannel) //receiving value
}
谁能帮我理解这个概念?
解决方案
for ... range
只有在从通道接收到所有值并且通道已关闭时,通道才会终止。
在您的示例中,您希望在延迟函数中关闭通道,但这只会在main()
返回时运行。但main()
只有在循环结束时才会返回。这就是死锁的原因。for
循环等待通道关闭,关闭通道等待 for 循环结束。
当您使用循环从通道中准确接收 5 个值时,它会起作用,因为启动的 goroutines 会在其上发送 5 个值。此循环不会等待通道关闭,因此循环可以结束,main()
函数也可以结束。
这就是为什么发送者应该关闭通道(而不是接收者),并且问题立即得到解决:
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
推荐阅读
- python - 从launchctl运行python脚本时Mac找不到chromedriver
- javascript - 哪些类型的副作用是由突变引起的?
- android - 如何用不同的颜色绘制相同的png图标?
- bitbucket - Netlify CMS - 来自 BitBucket 的博客文章显示在前端而不是后端 CMS
- python - 模块中的功能从一开始就无法识别
- mysql - OroCommerce 4.1.2 UTF8MB4 安装错误“1071 指定的密钥太长;最大密钥长度为 3072 字节”
- c - C 中的变量未声明(在此函数中首次使用)错误
- javascript - for循环内for循环无法正常工作多次重复相同的值Javascript
- javascript - 仅将 jquery 代码应用于手机和平板电脑
- asp.net-mvc - RemoveRange 不删除所有记录