我正在玩https://tour.golang.org/concurrency/5上显示的代码。我的想法是,我可以通过摆脱退出频道来简化代码,并保持正确的程序行为 - 仅用于学习目的。
这是我得到的代码(为了更好的可读性,简化了它):
package main
import "fmt"
import "time"
func sendNumbers(c chan int) {
for i := 0; i < 2; i++ {
c <- i
}
}
func main() {
c := make(chan int)
go func() {
for i := 0; i < 2; i++ {
fmt.Println(<-c)
}
}()
time.Sleep(0 * time.Second)
sendNumbers(c)
}
在这段代码中,我生成的go例程应该能够在返回之前接收2个数字。我接下来调用的sendNumbers()函数恰好将2个数字发送到通道c。
所以,程序的预期输出是2行:0和1.但是,当我在页面上运行代码时,我得到的只是包含0的单行。
注意
time.Sleep(0 * time.Second)
虽然我在调用sendNumbers(c)之前故意添加了。如果我将其更改为
time.Sleep(1 * time.Second)
输出变为预期:
0
1
所以,我对发生的事情感到困惑。有人可以解释发生了什么吗?在调用sendNumbers()之前,无论发送和接收块是多少都不应该通过?
答案 0 :(得分:2)
在Go中,只要主函数返回,程序就会退出,无论其他goroutine是否仍在运行。如果要确保主函数不会过早退出,则需要一些同步机制。 https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
你绝对不必使用同步原语,你也可以只使用通道,可以说这是一种更惯用的方法。