下面的代码运行得非常好:
package main
import (
"fmt"
)
func my_func(c chan int){
fmt.Println(<-c)
}
func main(){
c := make(chan int)
go my_func(c)
c<-3
}
游乐场_1
但是如果我改变
c<-3
to
time.Sleep(time.Second)
c<-3
游乐场_2
我的代码不执行。
我的直觉是main
返回之前my_func
完成执行,但似乎添加暂停应该不会有任何效果。我完全迷失在这个简单的例子中,这里发生了什么?
当。。。的时候main
函数结束,程序也随之结束。它不会等待其他 goroutine 完成。
引用自Go 语言规范:程序执行:
程序执行首先初始化主包,然后调用函数main
。当该函数调用返回时,程序退出。它不等待其他(非main
) goroutine 来完成。
所以简单地当你main
如果函数通过在通道上发送值而成功,程序可能会立即终止,然后其他 goroutine 有机会将接收到的值打印到控制台。
如果要确保将值打印到控制台,则必须将其与退出事件同步main
功能:
带有“完成”通道的示例(尝试一下去游乐场):
func my_func(c, done chan int) {
fmt.Println(<-c)
done <- 1
}
func main() {
c := make(chan int)
done := make(chan int)
go my_func(c, done)
time.Sleep(time.Second)
c <- 3
<-done
}
Since done
也是一个无缓冲通道,在末尾处从它接收main
函数必须等待发送一个值done
通道,在通道上发送值之后发生c
已收到并打印到控制台。
对看似不确定的运行的解释:
Goroutine 可以并行执行,也可以不并行执行同时。同步可确保某些事件先于其他事件发生。这是你得到的唯一保证,也是你唯一应该依赖的东西。
2个这样的例子发生在之前:
- The
go
启动新 goroutine 的语句发生在 goroutine 执行开始之前。
- 通道上的发送发生在该通道的相应接收完成之前。
欲了解更多详细信息,请阅读Go 内存模型.
回到你的例子:
来自无缓冲通道的接收发生在该通道上的发送完成之前。
所以你得到的唯一保证是运行的 goroutinemy_func()
将从通道接收值c
来自main()
。但是一旦收到该值,main
功能may继续,但由于发送后没有更多语句,它只是与程序一起结束。是否非main
Goroutine 将有time or chance打印它fmt.Println()
is 没有定义的.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)