Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding struct vs pointer to struct in struct used as pointer

Tags:

struct

go

If I have a struct type A which is used as a pointer (has pointer receivers only, the constructor returns *A, etc.), what is the difference between embedding a struct type B as B versus *B?

That is, what is the difference between

type B struct {...}
type A struct {
    B
    // ...
}

and

type B struct {...}
type A struct {
    *B
    // ...
}

For example, is there ever copying of the embedded field?

Edit: I should also mention that the embedded struct B only has pointer receivers.

like image 579
RobertR Avatar asked Sep 05 '25 20:09

RobertR


1 Answers

The zero values of the two structures are different, which can be a significant ergonomic difference.

Consider an embedded type

type B struct {
    X int
}

func (b *B) Print() { fmt.Printf("%d\n", b.X) }

If we embed this directly as an object

type AObj struct {
    B
}

then the zero value of type AObj includes an embedded object of type B, which also has its zero value, and therefore we can safely

var aObj AObj
aObj.Print() // prints 0

But if we instead embed a pointer

type APtr struct {
    *B
}

the zero value of this struct has a nil pointer value, and we can't really use it directly.

var aPtr APtr
aPtr.Print() // panics

Objects get copied in hopefully the way you might expect. If you create a new AObj object, it gets a copy of the embedded B.

aObj2 := aObj
aObj.X = 1
aObj2.Print() // prints 0, because it has a copy

If you create a new APtr object, it gets a copy of the *B, which means it shares the underlying concrete object.

aPtr.B = &B{}
aPtr2 := aPtr
aPtr.X = 1
aPtr2.Print() // prints 1, because both objects point at the same B

Runnable example at https://play.golang.org/p/XmOgegwVFeE

like image 185
David Maze Avatar answered Sep 10 '25 12:09

David Maze