go for range slice 和 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-range 循环中重用了 for 循环变量。


当 goroutine 有机会启动时,vmight的值已被修改。所以打印结果将是"three,three,three".


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


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

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


我不明白为什么。指针有什么不同或有什么不同的机制吗?


我从这篇文章中读到了这个。但海报没有说明原因。或者这只是一个事件,输出是正确的。


青春有我
浏览 196回答 1
1回答

慕丝7291255

在第一个循环中,v是一个项目的值field。因为v是可寻址的,所以它被自动引用为该print()方法的指针接收者。所以v.print()使用的地址v本身,而地址的内容被覆盖在循环的每次迭代。当您更改声明以使用 a 时*field,v现在是一个指向field值的指针。v.print()在这种情况下调用时,您正在操作v指向的值,该值存储在 中data,并且覆盖v无效。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go