Reputation: 162
I had deep dived in some comparisons about deep or shallow copy while passing a struct with primitive and pointer fields. Like:
type Copy struct {
age int
ac *AnotherCopy
}
type AnotherCopy struct {
surname string
}
func main() {
s := Copy{
age: 20,
ac: &AnotherCopy{surname: "Relic"},
}
passIt(&s)
fmt.Printf("main s: %p\n", &s)
}
func passIt(s *Copy) {
f := *s
fmt.Printf("s: %p\n", &*s)
fmt.Printf("f: %p\n", &f)
f.age = 26
f.ac.surname = "Walker"
fmt.Printf("%v %s\n", f, f.ac.surname)
fmt.Printf("%v %s\n", *s, s.ac.surname)
}
The result is
s: 0xc000010230
f: 0xc000010250
{26 0xc000010240} Walker
{20 0xc000010240} Walker
main s: 0xc000010230
What I can see here is that, when we pass a struct with primitive and composite types, It copies deeply primitive types and copies shallowly pointer (reference) fields.
I have read some articles about that process and there is a conflict between thoughts.
The question is what should we call that process? Deep copy or shallow copy? and if we call the process as only shallow copy, is this wrong? Can you clarify me please?
Upvotes: -2
Views: 1272
Reputation: 3328
In your question you mention "primitive and composite types" as being different, and I think that is the root of your confusion here. Go does not differentiate between primitive and composite types, but between pointer types and value types. "Primitive" types (int
, int32
, float64
, etc.) are value types, but so are struct
s (and also arrays). Pointers to other types, maps, slices, channels, and interfaces are all pointer types.
The direct answer to your question is, as one comment mentions, that copies in Go (via variable assignment, etc.) are "shallow copies" in that Go does not dereference pointer types and create new underlying copies. However, since struct
type things are not pointer types, it's completely possible for a composite value to be "deep copied".
If you want to see this in action, try modifying your example code so that the ac
field on your Copy
type is a plain struct rather than a pointer to a struct:
type Copy struct {
age int
ac AnotherCopy
}
You should then see that creating a copy of a Copy
and setting the ac.surname
field doesn't change the value of the ac.surname
field on the original struct.
Upvotes: -2