为了账号安全,请及时绑定邮箱和手机立即绑定

Go 频道发布、接收和 go 例程调度

Go 频道发布、接收和 go 例程调度

Go
慕森王 2022-06-27 16:33:34
我有以下一段 go 脚本,我对读取数据的通道和 go 例程的执行顺序有疑问。package mainimport "fmt"func squares(c chan int) {    fmt.Println("started squares goroutine...")    for num := range c {        //num := <-c        fmt.Println(num * num)    }    fmt.Println("exiting squares goroutine...")}func main() {    fmt.Println("main() started")    c := make(chan int, 3)    go squares(c)    c <- 1    printChannel(c)    c <- 2    printChannel(c)    c <- 3    printChannel(c)    c <- 4    fmt.Println("after publish 4")    printChannel(c)    c <- 5    fmt.Println("after publish 5")    printChannel(c)    c <- 6    printChannel(c)    c <- 7    printChannel(c)    c <- 8    printChannel(c)    fmt.Println("main() stopped")}func printChannel(c chan int) {    fmt.Println("length: ",len(c))    fmt.Println("capacity: ",cap(c))    }输出:main() startedlength:  1capacity:  3length:  2capacity:  3length:  3capacity:  3started squares goroutine...14916after publish 4length:  0capacity:  3after publish 5length:  0capacity:  3length:  1capacity:  3length:  2capacity:  3length:  3capacity:  3main() stopped问题:创建的通道 ch 的容量为 3,但在将 4 发布到通道之前,通道不会在方块 go 例程中读取,如果容量为 3,其中 4 存储在通道中将所有数字从通道中读取出来后,再次将数字 5 发布到通道,但通道的长度仍然为 0,为什么?代码的 Goplayground 链接:https: //play.golang.org/p/TmCcZt5n58f
查看完整描述

1 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

无法保证 goroutine 的执行顺序,也无法保证 goroutine 何时中断(I/O,包括打印到 stdout,将是重新调度的最常见原因)。

对于您的第一个问题:您可以看到16之前正在打印after publish 4。这意味着squaresgoroutine 在主 goroutine 开始打印信息之前从通道读取并打印正方形。当主 goroutine 尝试打印通道的长度时,4它已经消失了。

同样,发送5到通道后,squaresgoroutine 已经收到了,但还没有打印出来。它在打印之前被中断。这意味着通道又是空的,但我们还没有看到25

如果您多次运行示例,您将看到不同的输出。有时squaresgoroutine 会一直上升到64,有时不会。这是完全正常的。在普通代码中,您需要确保在退出之前等待数据被使用,并且您不会依赖于不同 goroutine 的执行顺序或时间。


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 201 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号