先来看看对copy的错误使用

  1. func main() {
  2. nums:=[]int{1,2,3,4,5}
  3. fmt.Println(" len cap address")
  4. fmt.Print("111---",len(nums),cap(nums))
  5. fmt.Printf(" %p\n",nums)//0xc4200181e0
  6. a:=nums[:3]
  7. fmt.Print("222---",len(a),cap(a))
  8. fmt.Printf(" %p\n",a)//0xc4200181e0 一样
  9. //output: 222--- 3 5
  10. b:=nums[:3:3] //第二个冒号 设置cap的
  11. n:=copy(b,nums[:3:3]) //第二个冒号 设置cap的
  12. fmt.Print("333---",len(b),cap(b))
  13. fmt.Printf(" %p\n",b)//0xc4200181e0 一样
  14. //output: 333--- 3 3
  15. fmt.Println(n,b)
  16. nums[0]=55
  17. fmt.Println(nums,a,b)
  18. }

发现 nums[0]修改了数据后,其他全部都改变了,并且地址都一样,想了想 到底哪里出了问题呢? 是 copy 的问题?

  1. len cap address
  2. 111---5 5 0xc4200181e0
  3. 222---3 5 0xc4200181e0
  4. 333---3 3 0xc4200181e0
  5. 3 [1 2 3]
  6. [55 2 3 4 5] [55 2 3] [55 2 3]

发现上面的copy前的对象没有分配内存,使用了一样的内存地址导致的,把上面的代码做一些修改:

  1. b:=nums[:3:3] //第二个冒号 设置cap的
  2. // 修改为
  3. var b =make([]int,len(nums[:3:3]))

这次修改之后,运行的结果就和预期一样了,b的值不会被修改

  1. len cap address
  2. 111---5 5 0xc4200181e0
  3. 222---3 5 0xc4200181e0
  4. 333---3 3 0xc42000a400
  5. 3 [1 2 3]
  6. [55 2 3 4 5] [55 2 3] [1 2 3]

golang深拷贝任意结构代码:

  1. // Clone 完整复制数据
  2. func Clone(a, b interface{}) error {
  3. buff := new(bytes.Buffer)
  4. enc := gob.NewEncoder(buff)
  5. dec := gob.NewDecoder(buff)
  6. if err := enc.Encode(a); err != nil {
  7. return err
  8. }
  9. if err := dec.Decode(b); err != nil {
  10. return err
  11. }
  12. return nil
  13. }

参考

golang对slice的深拷贝copy