Embedding in Go

Go supports defining is-a relationships using an embedded type.

Fields and methods in a struct have a has-a relationship

E.g.  Person has-a name and email.

type Person struct {
	Name   string
	Email  string

Embedding to define an is-a relationships  is declared with a type but no explicit field name. The unqualified type name acts as the field name.

type Employee struct { 
      EmployeeID string 

This way the Person struct can be accessed using the type name:

accountant := new(Employee)

We can also invoke any Person methods directly on the Employee object

accountant := new(Employee)

We cannot embed a slice or a map

type Employee struct { 
 EmployeeID string 

This will give  a syntax error: unexpected [, expecting field name or embedded type

A workaround will be defining a type and then embedding

type SpecialPeople []Person

type Employee struct { 
 EmployeeID string 

The spec in Go describes embedding as below:

EmbeddedField = [ "*" ] TypeName .

Embed by-pointer

The advantage of embedding by reference is that  you are embedding all the functionality of a type without needing to know when it is instantiated. The major application of this would be to have thousands of instances sharing a single underlying data structure. This can significantly reduce memory consumption.

type Image struct {
     data [5][5]

type Block struct {
   show bool

Because, the unqualified type name acts as the field name for an embedded struct, we can’t have an embedded struct and its pointer in the same struct

struct {
	T     // conflicts with embedded field *T and *P.T
	*T    // conflicts with embedded field T and *P.T
	*P.T  // conflicts with embedded field T and *T

Promotion of fields or methods

All field or method calls for embedded type objects are resolved at compile-time without the use of a virtual table. A field or method of an embedded field in a struct is called promoted.

type Person struct { 
      Name   string 
      Email  string 
func (p *Person) FreeGift() int64{ 
     return 100 

type Employee struct {       
     EmployeeID string  

In this example person.FreeGift()  and employee.FreeGift() is the same so the method is promoted. Promotion  occurs only at the first level.


However, if we have a method with the same name defined on the parent struct as below, then employee.FreeGift() will invoke the method on the Employee struct

func (e *Employee) FreeGift() int64{ 
      return 200

In the above example, calling person.FreeGift() and employee.Person.FreeGift() will invoke the method on the Person struct


One very important design aspect to remember is, if you plan to use an embedded struct and the embedded type has non-exported fields or methods,  those are completely inaccessible to you in a separate package.

Embedding Interfaces

Embedding an interface will add all (exported and non-exported) methods of the embedded interface to the enclosing interface.

type ImageWriter interface { 
      Read(b Buffer) bool 
      Write(b Buffer) bool 
type ImageFile interface { 
     ImageWriter  // same as adding the methods of ImageWriter 




Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s