Go中的指针混淆

我很难理解下面的代码,我让它工作但仍然不明白。如果有人可以揭开它的神秘面纱,那将非常有帮助


在下面的代码中,标志名称未更新为“已更改”


package main


import "fmt"


type Command struct {

   Name  string

   Flags []Flag

}


type Flag struct {

   Name      string

   Shorthand string

}


func getCommand() *Command {

   return &Command{Name: "Hello", Flags: []Flag{{"version", "v"}}}

}


func change(cmd *Command) {

   for _, flg := range cmd.Flags {

       flg.Name = "Changed"

   }


}


func main() {

   cmd := getCommand()

   change(cmd)

   fmt.Println(cmd.Flags[0])


}


正确的代码。标志名称更改为“已更改”


package main


import "fmt"


type Command struct {

    Name  string

    Flags []*Flag

}


type Flag struct {

    Name      string

    Shorthand string

}


func getCommand() *Command {

    return &Command{Name: "Hello", Flags: []*Flag{{"version", "v"}}}

}


func change(cmd *Command) {

    for _, flg := range cmd.Flags {

        flg.Name = "Changed"

    }


}


func main() {

    cmd := getCommand()

    change(cmd)

    fmt.Println(cmd.Flags[0])


}


我敢肯定,我的困惑可能是微不足道的,但这浪费了我几个小时


芜湖不芜
浏览 118回答 2
2回答

牧羊人nacy

在您的第一个版本中,当您这样做时:for _, flg := range cmd.Flags {    flg.Name = "Changed"}flg是类型的局部变量Flag。在循环的每次迭代中for,range设置flg为 中下一项的副本cmd.Flags。所以当你改变它时,在那个循环之外没有任何变化。在您的第二个版本中,当您执行该循环时,flg是 type 的局部变量*Flag,因此当 range 将其设置为 in 中下一个项目的副本时cmd.Flags,flg它指向您尝试改变的数据,并且改变它实际上会改变该数据.

不负相思意

for _, flg := range cmd.Flags {        flg.Name = "Changed"    }这部分是确切的罪魁祸首。range 返回的第一个值是索引(此处忽略),第二个值是实际数据的副本。当您在循环中使用它时(flg.Name=...),您正在将值分配给副本的名称字段。你可以这样做:for index, _ := range cmd.Flags {        cmd.Flags[index].Name = "Changed"    }在第二种情况下,您将引用(或内存地址)副本的名称字段分配给标志,因此该内存地址的值会更改。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go