如果包含 time.Sleep,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

}


但是如果我改变


c<-3


time.Sleep(time.Second)

c<-3


我的代码不执行。


我的直觉是main在my_func完成执行之前以某种方式返回,但似乎添加暂停应该没有任何效果。我完全迷失在这个简单的例子中,这里发生了什么?


动漫人物
浏览 303回答 1
1回答

侃侃无极

当main函数结束时,程序也随之结束。它不会等待其他 goroutine 完成。引用Go 语言规范:程序执行:程序执行首先初始化主包,然后调用函数main。当该函数调用返回时,程序退出。它不会等待其他(非main)goroutine 完成。因此,当您的main函数通过在通道上发送值而成功时,程序可能会立即终止,然后另一个 goroutine 有机会将接收到的值打印到控制台。如果要确保将值打印到控制台,则必须将其与退出main函数的事件同步:带有“完成”频道的示例(在Go Playground上尝试):func&nbsp;my_func(c,&nbsp;done&nbsp;chan&nbsp;int)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(<-c) &nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;<-&nbsp;1}func&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;:=&nbsp;make(chan&nbsp;int) &nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;:=&nbsp;make(chan&nbsp;int)&nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;my_func(c,&nbsp;done) &nbsp;&nbsp;&nbsp;&nbsp;time.Sleep(time.Second) &nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;<-&nbsp;3 &nbsp;&nbsp;&nbsp;&nbsp;<-done}由于done也是一个无缓冲通道,因此在main函数结束时从它接收必须等待在done通道上发送一个值,这c是在接收到通道上发送的值并将其打印到控制台之后发生的。对看似不确定的运行的解释:够程可能会或可能不会被并行执行在同一时间。同步确保某些事件发生在其他事件之前。这是您获得的唯一保证,也是您唯一应该依赖的东西。之前发生过2 个这样的例子:go启动新 goroutine的语句发生在 goroutine 开始执行之前。通道上的发送发生在来自该通道的相应接收完成之前。有关更多详细信息,请阅读Go 内存模型。回到你的例子:来自无缓冲通道的接收发生在该通道上的发送完成之前。所以你得到的唯一保证是运行的 goroutinemy_func()将接收c从main().&nbsp;但是一旦接收到值,该main函数可能会继续,但由于发送后没有更多语句,它只是结束 - 与程序一起。无论非main够程将有时间或机会与打印fmt.Println()是没有定义。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go