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
", 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