4 thoughts
last posted Aug. 19, 2014, 3:01 p.m.
get stream as: markdown or atom

Interfaces in Go are pretty interesting. They're declared as a set of methods that a type -- any type -- must implement to satisfy the interface.

Types in Go don't state their compliance -- or intention to comply -- with an interface like classes do in other languages like Java. They either do or do not satisfy the interface by supporting the methods.


Methods in Go can have a struct receiver or a pointer receiver. For example, given a Person struct:

type Person struct { name string }

You could implement a Hello() method as either

func (p Person) Hello() string { return "Hello " + p.name }


func (p *Person) Hello() string { return "Hello " + p.name }

The difference between the two is what p is: in the case of the former, p is a copy of the Person struct, and any changes you make won't be reflected in the caller.

In the case of the latter -- where p is a pointer receiver, *Person -- p is mutable, and its contents can be changed. Another difference is that when you use a pointer receiver the contents of p don't need to be copied before executing the Hello() method. This can be really important for large structs.


The fact that you don't have to explicitly declare that you implement an interface means they're easy to treat as emergent behavior: as you realize you need two different kinds of People, you declare an interface, Individual.

type Individual interface { Hello() string }


Something that's bitten me a few times -- although I'm slowly internalizing it -- is the fact that while *Person is a pointer to a Person struct, *Individual is not a pointer to "any type implementing Individual".

*Individual is a pointer to the interface itself.

A parameter that's an interface type doesn't tell you anything about whether it's a pointer or a copy. Either can implement the interface, depending on how the methods are declared.

reposted to TIL