go 协程问题

func main() {
    chanOwner := func() <-chan int {
        results := make(chan int, 5)
        go func() {
            defer close(results)
            for i := 0; i <= 5; i++ {
                results <- i
            }
        }()
        for v := range results {
            fmt.Println(v)
        }
        return results
    }
    chanOwner()
}
// 输出为什么是1 2 3 4 5 而不是 0 0 0 0 0 ?

共 4 个回复


lfwzc

为什么应该是0 0 0 0 0?

# 0

samete

1楼可以解释下么?

# 1

superqbb

因为主线程执行到

for v := range results {
    fmt.Println(v)
}

时, channel为空,会等待协程写入数据,当协程写入数据时,就会被主协程捕获并打印。由于只有一个协程在写消息,因此主协程打印的顺序没有乱。你可以通过运行下面的代码感受一下

func main() {
    chanOwner := func() <-chan int {
        results := make(chan int, 5)
        go func() {
            defer fmt.Println("释放channel")
            defer close(results)
            for i := 0; i <= 5; i++ {
                fmt.Printf("发送消息:%v\n",i)
                results <- i
                time.Sleep(1*time.Second)
            }
        }()
        for v := range results {
            fmt.Println(v)
        }
        fmt.Println("读取完毕")
        return results
    }
    chanOwner()
}
# 2

samete

谢谢3楼的回答!

# 3