Skip to content

Understanding Go Interfaces: Pointer Receivers vs. Value Receivers

Published:

Table of contents

Open Table of contents

Intro

In Go, interfaces are a powerful way to define behaviors. One interesting aspect of how interfaces work in Go revolves around the use of pointer receivers and value receivers in methods. This post will explain this peculiarity and demonstrate it with examples.

Pointer Receivers in Interfaces

When a method in an interface has a pointer receiver, only pointers of the type that implements this interface can be used to satisfy the interface.

Example:

package main

import (
    "fmt"
)

type Describer interface {
    Describe()
}

type Person struct {
    Name string
    Age  int
}

func (p *Person) Describe() {
    fmt.Printf("%v is %v years old\n", p.Name, p.Age)
}

func main() {
    var d1 Describer
    p1 := Person{"Sam", 25}
    d1 = &p1 // This works
    d1.Describe()
    // d1 = p1 // This will not work
}

In this example, Describe method has a pointer receiver (*Person). Therefore, only a pointer (&p1) can be assigned to an interface variable of type Describer.

Value Receivers in Interfaces

Conversely, if a method in an interface has a value receiver, both values and pointers of the implementing type can be used to satisfy the interface.

Example:

package main

import (
    "fmt"
)

type Describer interface {
    Describe()
}

type Animal struct {
    Species string
}

func (a Animal) Describe() {
    fmt.Printf("An animal of type %v\n", a.Species)
}

func main() {
    var d1 Describer
    a1 := Animal{"Gopher"}
    d1 = a1 // This works
    d1.Describe()
    a2 := &Animal{"Elephant"}
    d1 = a2 // This also works
    d1.Describe()
}

In this case, since Describe method has a value receiver (Animal), both a value (a1) and a pointer (a2) can be assigned to the Describer interface.

Conclusion

Understanding the difference between pointer receivers and value receivers in interfaces is crucial in Go. It affects how you implement interfaces and how you can use them in your code.

Remember: