skip to content

Search

Receivers in Go

2 min read

Methods associated with specific types.

Receivers in Go are methods (behaviours) tightly coupled to a specific type. A receiver is defined in between func and the name of the method.

type Counter struct {
    Count int
}
 
func (ctr Counter) Increment () {
    ctr.Count++
}

This Increment method acts on a struct of type Counter.

Value Receivers vs. Pointer Receivers

Value

The above is an example of a value receiver ctr Counter. The method acts on a copy of the value ctr. Changes made inside the method do not affect the original value. This is because Go is pass-by-value, meaning it creates a copy within the function.

type Counter struct {
    Count int
}
 
func (ctr Counter) Increment () {
    ctr.Count++
}
 
func main() {
    myCounter := Counter{Count: 0}
    myCounter.Increment()
    println("Count:", myCounter.Count) // 0
}

Pointer

Also known as passing by reference, when you pass a pointer as the receiver type (ctr *Counter below), the method acts on the actual value. This is often used to avoid the overhead of copying large structs.

type Counter struct {
    Count int
}
 
func (ctr *Counter) Increment () {
    ctr.Count++
}
 
func main() {
    myCounter := Counter{Count: 0}
    myCounter.Increment()
    println("Count:", myCounter.Count) // 1
}

Which receiver type to use

TL;DR - you almost always want to use a pointer receiver, especially if:

  • You are updating the state of the receiver (changing the value)
  • You want to avoiding copying large structs
  • You want consistency with all methods for a type. If some methods use a pointer receiver, they can all use pointer receivers.
  • You want to use nil pointers. Methods with value receivers whill cause a panic of called on a nil value.