-3

I have a complex data structure, which defines a type P, and I'd like to perform a deep copy of an instance of such a data structure. I have found this library but, considering the semantics of the Go language, wouldn't a method like the following be more idiomatic?:

func (receiver P) copy() *P{
   return &receiver
}

Since the method receives a value of type P (and values are always passed by copy), the result should be a reference to a deep copy of the source, like in this example:

src := new(P)
dcp := src.copy()

Indeed,

src != dst => true
reflect.DeepEqual(*src, *dst) => true
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Luca Marzi
  • 786
  • 2
  • 8
  • 24

1 Answers1

2

this test shows that your method doesn't do a copy

package main

import (
    "fmt"
)

type teapot struct {
   t []string
}
type P struct {
   a string
   b teapot
}

func (receiver P) copy() *P{
   return &receiver
}

func main() {

x:=new(P)
x.b.t=[]string{"aa","bb"}
y:=x.copy()

y.b.t[1]="cc"  // y is altered but x should be the same

fmt.Println(x)  // but as you can see...

}

https://play.golang.org/p/xL-E4XKNXYe

Vorsprung
  • 32,923
  • 5
  • 39
  • 63
  • Ok, so, basically, I can either devise a way to make an actual copy of my data structure or use the library https://github.com/jinzhu/copier, right? – Luca Marzi Feb 16 '19 at 12:59
  • See https://stackoverflow.com/questions/23033143/is-there-a-built-in-function-in-go-for-making-copies-of-arbitrary-maps – Vorsprung Feb 16 '19 at 13:40
  • @LucaMarzi, to understand why things work this way in Go, you should understand several things: 1) in Go,everything, ever is passed by value; 2) pointers (values of any pointer type) are itself values and are passed by value, too (sort of obviously); 3) _by their nature_ all variables containing the same pointer value refer to the same object in memory; 4) some types either are pointers (maps, channels) or include pointers (strings, slices); custom Go types may be of either of these two varietes, too. – kostix Feb 17 '19 at 16:02
  • @LucaMarzi, Once you've absorbed this, the next thing to think through is that values of types which are pointers or contain pointer fields may form arbitrary hierarchies (a tree containing maps in its leaves is a silly but simple example), and how to deep-copy a value _of a particular type_ is an open question which cannot have one "true" answer. To illustrate, let's consider my silly tree example. When deep-copying a tree, _usually_ copying—duplicating—all the nodes is indeed a sensible thing, but you cannot say the same thing about the values the tree's leaves point to— – kostix Feb 17 '19 at 16:06
  • @LucaMarzi,—those might need be shared across all the existing trees. Now consider that blindly copying the tree's nodes has no sense: in different trees, each node should refer to the nodes of its own tree, not the tree the nodes were copied from. Please think of it. Go does not have any special syntax for "automatic" deep-copying simply because how to do a deep copy has to be decided on a case-by-case basis, there's no one-size-fits-all solution. – kostix Feb 17 '19 at 16:08