V
Vel·ToolKit
Simple · Fast · Ready to use
EN
Chapter 11 of 20

Methods

Value receivers vs pointer receivers

Defining Methods on a Type

A method is essentially a function with a receiver. The receiver can be any named type defined in the current package.

package main

import "fmt"

type Rect struct{ W, H float64 }

func (r Rect) Area() float64 {
    return r.W * r.H
}

func main() {
    r := Rect{3, 4}
    fmt.Println(r.Area()) // 12
}

Value Receiver vs Pointer Receiver

  • Value receiver: the receiver is copied on call; mutations inside the method don't affect the caller
  • Pointer receiver: the method can modify the receiver; avoids the copy cost of a large struct
  • General rule: keep the receiver form consistent across a type's methods; use a pointer receiver when you must mutate state or the type is large
package main

import "fmt"

type Rect struct{ W, H float64 }

func (r *Rect) Scale(f float64) {
    r.W *= f
    r.H *= f
}

func main() {
    r := Rect{3, 4}
    r.Scale(2)     // Go takes the address automatically
    fmt.Println(r) // {6 8}
}

Method Values and Method Expressions

A method can be referenced like an ordinary function: r.Area is a method value (receiver bound), Rect.Area is a method expression (receiver as the first argument).

package main

import "fmt"

type Rect struct{ W, H float64 }

func (r Rect) Area() float64 { return r.W * r.H }

func main() {
    r := Rect{3, 4}

    fn := r.Area      // method value
    fmt.Println(fn()) // 12

    expr := Rect.Area  // method expression
    fmt.Println(expr(r)) // 12
}