为了账号安全,请及时绑定邮箱和手机立即绑定

Go中的指针混淆

Go中的指针混淆

Go
芜湖不芜 2022-05-23 17:21:28
我很难理解下面的代码,我让它工作但仍然不明白。如果有人可以揭开它的神秘面纱,那将非常有帮助在下面的代码中,标志名称未更新为“已更改”package mainimport "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 mainimport "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])}我敢肯定,我的困惑可能是微不足道的,但这浪费了我几个小时
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

在您的第一个版本中,当您这样做时:


for _, flg := range cmd.Flags {

    flg.Name = "Changed"

}

flg是类型的局部变量Flag。在循环的每次迭代中for,range设置flg为 中下一项的副本cmd.Flags。所以当你改变它时,在那个循环之外没有任何变化。


在您的第二个版本中,当您执行该循环时,flg是 type 的局部变量*Flag,因此当 range 将其设置为 in 中下一个项目的副本时cmd.Flags,flg它指向您尝试改变的数据,并且改变它实际上会改变该数据.


查看完整回答
反对 回复 2022-05-23
?
不负相思意

TA贡献1777条经验 获得超10个赞

for _, flg := range cmd.Flags {

        flg.Name = "Changed"

    }

这部分是确切的罪魁祸首。range 返回的第一个值是索引(此处忽略),第二个值是实际数据的副本。当您在循环中使用它时(flg.Name=...),您正在将值分配给副本的名称字段。你可以这样做:


for index, _ := range cmd.Flags {

        cmd.Flags[index].Name = "Changed"

    }

在第二种情况下,您将引用(或内存地址)副本的名称字段分配给标志,因此该内存地址的值会更改。


查看完整回答
反对 回复 2022-05-23
  • 2 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信