Go结构体映射属性更新问题:修改映射中结构体属性不生效
Go中修改map结构体值不生效的原因及解决办法
你猜的没错,问题核心就是值拷贝 vs 引用类型的差异,这和JavaScript的行为逻辑不一样:
为什么JS里能直接改?
在JavaScript中,数组、对象这类都是引用类型,你从数组/对象里取出元素时,拿到的是原对象的引用指针,修改这个引用的属性会直接同步到原对象上。
Go里为啥改不动?
你的代码里,people["nick"]取出的是person结构体的完整值拷贝,不是原结构体的引用。所以你修改nick.Age只是改了这个临时拷贝的属性,原map里存储的person完全没被影响。
解决办法
方法1:用指针类型作为map的value(推荐)
把map的value类型改成*person,这样存进去的是结构体指针,取出来的也是同一个指针,修改指针指向的属性会直接作用在原结构体上:
type person struct { Age int } var people map[string]*person func main() { people = make(map[string]*person) people["nick"] = &person{Age: 1} // 存储结构体指针 log.Println(people["nick"].Age) nick := people["nick"] nick.Age = 2 log.Println(people["nick"].Age) // 输出2,符合预期 }
方法2:修改后重新赋值给map
如果不想用指针,也可以修改临时拷贝后,把整个结构体重新存回map:
type person struct { Age int } var people map[string]person func main() { people = make(map[string]person) people["nick"] = person{Age: 1} log.Println(people["nick"].Age) nick := people["nick"] nick.Age = 2 people["nick"] = nick // 将修改后的结构体放回map log.Println(people["nick"].Age) // 输出2 }
补充说明
Go里的map本身是引用类型,但map的value如果是值类型(比如person结构体),取出时依然会触发值拷贝。只有当value是指针、slice这类引用类型时,取出的才是原数据的引用。
内容的提问来源于stack exchange,提问作者Patrick Trester
相关产品推荐
相关产品推荐

