Aka*_*all 9 concurrency channel go goroutine
以下代码运行完全正常:
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
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我改变
c<-3
Run Code Online (Sandbox Code Playgroud)
至
time.Sleep(time.Second)
c<-3
Run Code Online (Sandbox Code Playgroud)
我的代码没有执行.
我的直觉是main在my_func完成执行之前以某种方式返回,但似乎添加暂停应该没有任何效果.我完全迷失在这个简单的例子上,这里发生了什么?
icz*_*cza 12
当main函数结束时,程序以它结束.它不等待其他goroutines完成.
引用Go语言规范:程序执行:
程序执行从初始化主包然后调用该函数开始
main.当该函数调用返回时,程序退出.它不等待其他(非main)goroutines完成.
因此,当您的main函数通过在通道上发送值成功时,程序可能会立即终止,然后另一个goroutine有机会将接收到的值打印到控制台.
如果要确保将值打印到控制台,则必须将其与退出main函数的事件同步:
"完成"频道的示例(在Go Playground上尝试):
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
}
Run Code Online (Sandbox Code Playgroud)
由于done也是一个无缓冲的通道,在main功能结束时从它接收必须等待在done通道上发送一个值,这在c接收到通道上发送的值并打印到控制台后发生.
对看似不确定的运行的解释:
够程可能会或可能不会被并行执行在同一时间.同步可确保某些事件在其他事件发生之前发生.这是您获得的唯一保证,也是您应该依赖的唯一保证.这两个例子发生之前:
go启动新goroutine 的语句发生在goroutine执行开始之前.- 通道上的发送在该通道的相应接收完成之前发生.
有关更多详细信息,请参阅Go Memory Model.
回到你的例子:
来自无缓冲通道的接收在该通道上的发送完成之前发生.
因此,唯一可以保证的是,运行的goroutine my_func()将从c发送的通道接收值main().但是一旦收到该值,该main函数可能会继续,但由于发送后没有更多的语句,它只是结束 - 与程序一起.无论非main够程将有时间或机会与打印fmt.Println()是没有定义.