Go语言中结构体栈元素被覆盖?如何实现结构体深拷贝?
解决Go语言结构体栈的深拷贝问题
问题根源
你的问题出在浅拷贝上:Vehicle结构体中的Quantity是map[string]interface{}类型,属于引用类型。如果只是简单复制结构体,新实例和原实例会共享同一个map底层数据结构,修改原实例的map会同步影响栈中存储的实例,这就是为什么弹出栈时拿到的是修改后的20而不是入栈时的10。
实现深拷贝的clone方法
要实现深拷贝,需要为Vehicle创建一个新实例,同时为Quantitymap创建一个新的副本,把原map中的所有键值对逐一复制进去。以下是完整的clone方法实现:
func clone(v *Vehicle) *Vehicle { // 创建新的Vehicle实例,复制值类型字段Name cloned := &Vehicle{ Name: v.Name, // 初始化新的map Quantity: make(map[string]interface{}), } // 遍历原map,复制所有键值对到新map for key, value := range v.Quantity { cloned.Quantity[key] = value } return cloned }
补充说明
- 对于
Name这种字符串类型(值类型),直接赋值即可完成拷贝,因为字符串在Go中是不可变的,赋值会复制底层数据。 - 对于
Quantity这种引用类型的map,必须创建新的map并复制所有元素,才能避免和原实例共享底层数据。
修正后的操作示例
同时需要修正你代码中的几个语法错误(Go中函数用func而非function,字符串键需用双引号):
type Stack struct { stack []*Vehicle // 建议存储指针,避免不必要的结构体拷贝 } // 为Stack实现push方法 func (s *Stack) push(v *Vehicle) { s.stack = append(s.stack, v) } // 为Stack实现pop方法 func (s *Stack) pop() *Vehicle { if len(s.stack) == 0 { return nil } lastIdx := len(s.stack) - 1 v := s.stack[lastIdx] s.stack = s.stack[:lastIdx] return v } type Vehicle struct { Name string Quantity map[string]interface{} } func NewVehicle(name string) *Vehicle { v := &Vehicle{Name: name} v.Quantity = make(map[string]interface{}) return v } func clone(v *Vehicle) *Vehicle { cloned := &Vehicle{ Name: v.Name, Quantity: make(map[string]interface{}), } for k, val := range v.Quantity { cloned.Quantity[k] = val } return cloned } // 测试代码 func main() { m := NewVehicle("Two Wheeler") m.Quantity["a"] = 10 // 注意用双引号 stack := &Stack{} stack.push(clone(m)) m.Quantity["a"] = 20 popped := stack.pop() println(popped.Quantity["a"]) // 输出10,符合预期 }
额外建议
- 建议Stack存储
*Vehicle指针而非Vehicle值,这样可以减少结构体拷贝的开销,同时更符合深拷贝后的使用场景。 - 如果
Vehicle结构体未来添加更多引用类型字段(比如切片、其他结构体指针),需要在clone方法中对这些字段也做对应的深拷贝处理。
内容的提问来源于stack exchange,提问作者Deepak Sharma
相关产品推荐
相关产品推荐

