还未发布过话题
  • golang 循环中的闭包问题 at 2017年06月13日

    折腾了好一下,我也总算理清楚了,就是如@silenceshell 和@chanehua所说的,主要是指针传递,值传递和 Goroutine 执行顺序间的问题。

    func TestClosure() {
        data := []*field{{"one"}, {"two"}, {"three"}}
        for _, v := range data {
            go v.print()
        }
        time.Sleep(3 * time.Second)
    }
    

    这个版本能按序输出。循环中的 v 只定义了一次,赋值了三次,因为 data 是指针数组,所以 range 中传给 v 的是三个元素的指针,v 是指针类型,值各不相同,而在传给 Goroutine 时,v 值已经确定了,所以每次 for 循环时,go v.print() 都把当前循环的值都传去了。


    func TestClosure() {
        data := []*field{{"one"}, {"two"}, {"three"}}
        for _, v := range data {
            go func(){
            v.print()
            }()
        }
        time.Sleep(3 * time.Second)
    }
    

    这一版本中只输出了最后一个元素,因为在 Goroutine 下执行的顺序无法预估。这段中 for 都执行完了 go func(){}才执行,等到 v.print() 执行的时候,v 变量已经被迭代到最后一个元素了。下面的这段可以验证这点。

    func TestClosure() {
        data := []*field{{"one"}, {"two"}, {"three"}}
        for _, v := range data {
            fmt.Println("for")
            go func() {
                fmt.Println("go func")
                v.print()
            }()
        }
        time.Sleep(3 * time.Second)
    }