Go结构体CopyTree方法拷贝Map后修改副本导致原对象被修改如何解决
问题根因
- 你当前的
CopyTree实现并非完整深拷贝,仅完成了map实例本身的复制,没有对map值中包含的引用类型做递归拷贝,是导致修改副本影响原对象的核心原因:- 从代码可推断
childMap的value为[]int切片类型,切片属于引用类型,直接copy.childMap[key] = value仅复制了切片的头信息(底层数组指针、长度、容量),新旧对象的对应切片共享同一个底层数组,修改副本切片的元素、或在不触发扩容的前提下增删元素,都会同步修改原对象的对应切片。 - 如果
root字段是指针类型、或者treeMap存储的Symbol结构体包含指针/切片/map类引用字段,直接赋值也会导致新旧对象共享底层数据。
- 从代码可推断
- 指针接收者的使用没有问题,
ReplaceNodeCascade用指针接收者修改副本本身是合理的。
修复方案
修改CopyTree方法,对所有引用类型的value做深拷贝,切断新旧对象的底层数据关联:
func (e Expression) CopyTree() Expression { copy := NewEmptyExpression() // 若root为指针类型,需深拷贝指针指向的内容,示例:tmp := *e.root; copy.root = &tmp copy.root = e.root for key, value := range e.auxMap { // 若auxMap的value为引用类型,需补充对应深拷贝逻辑 copy.auxMap[key] = value } for key, value := range e.treeMap { // 若Symbol结构体包含引用类型字段,需调用Symbol的深拷贝方法赋值 copy.treeMap[key] = value } for key, value := range e.parentMap { copy.parentMap[key] = value } // 重点:深拷贝childMap的切片值 for key, value := range e.childMap { copiedSlice := make([]int, len(value)) copy(copiedSlice, value) copy.childMap[key] = copiedSlice } copy.updateDisplay() return copy }
额外检查项:
- 确认
Symbol结构体的字段,若存在引用类型,为Symbol实现对应的深拷贝方法,拷贝treeMap值时调用该方法。 - 确认
root字段类型,若为指针类型需补充根节点的深拷贝逻辑,避免共享根节点。
内容的提问来源于stack exchange,提问作者m.tracey
相关产品推荐
相关产品推荐

