go for range slice和goroutine方法调用,背后的逻辑

时间:2015-06-01 15:19:56

标签: go goroutine

代码如下:

package main

    import (
        "fmt"
        "time"
    )

    type field struct {
        name string
    }

    func (p *field) print() {
        fmt.Println(p.name)
    }

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

我知道代码错误,因为for循环变量在for-range循环中重用。

当goroutine有机会启动时,v的值可能已被修改。所以打印结果为"three,three,three"

但是当我们将数据变量修改为另一个声明时:

data := []*field{{"one"},{"two"},{"three"}}

打印结果为"one ,two,three"

我没有明白为什么。指针是否有任何不同或者是否有任何不同的机制?

我是从this article读到的。但海报并没有说明原因。或者只是输出正确的事件。

1 个答案:

答案 0 :(得分:1)

在第一个循环中,vfield项的。由于v是可寻址的,因此它会自动被引用为print()方法的指针接收器。所以v.print()正在使用v本身的地址,并且每次迭代循环都会覆盖该地址的内容。

当您更改声明以使用*field时,v现在是指向field值的指针。在这种情况下,当您致电v.print()时,您正在使用v指向的值进行操作,该值存储在data中,并且覆盖v无效。