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
}