Serhat Yılmaz
Serhat Yılmaz

Reputation: 162

Deep copy vs shallow copy for structs

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

Answers (1)

Austin
Austin

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 structs (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

Related Questions