liveBook · Manning

Method

As explained in 100 Go Mistakes and How to Avoid Them

A method is a Go function associated with a receiver type and invoked on a value or pointer of that type.

A method is a function attached to a Go type. Its receiver can be a value or a pointer. Choosing the wrong one can make a change disappear—or make a deferred call observe a value you did not expect. section 6.0 section 6.1

type customer struct {
    balance float64
}
 
func (c customer) add(v float64) {              #1
    c.balance += v
}
 
func main() {
    c := customer{balance: 100.}
    c.add(50.)
    fmt.Printf("balance: %.2f\n", c.balance)    #2
}

This `add` method changes a copy of `customer`. After `c.add(50.)`, the original balance is still `100.00`. Changing the receiver to `*customer`, as in the pointer-receiver version, makes the balance `150.00`. section 6.1

Use a pointer receiver when the method must change the receiver, including when it must append to a slice receiver, or when the type contains a field that cannot be copied. A pointer receiver can also avoid copying a large object; benchmark when size makes that choice uncertain. A value receiver copies the receiver, but not the objects reached through its pointer fields, so a value-receiver method can still change referenced data. When the choice remains unclear, prefer a pointer receiver. section 6.1 section 6.7

A deferred method call prints the earlier value

With `s := Struct{id: "foo"}`, `defer s.print()` followed by `s.id = "bar"` prints `foo` when `print` has a value receiver. The receiver was evaluated when the call was deferred. With a pointer receiver, the deferred call copies the pointer, and the later change to the pointed-to struct is visible: it prints `bar`. section 6.6.2

A nil receiver is not a nil error

A pointer-receiver method can be called on a nil pointer if it does not dereference that pointer. But returning a nil `*MultiError` from a method declared to return `error` produces a non-nil interface: an `err != nil` check succeeds even though formatting the error shows `<nil>`. Return an explicit `nil` when no validation errors were collected. section 6.4

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Works through receiver copying and deferred evaluation, but defers detailed pointer-versus-value performance analysis.
Examples
Contrasts balance-changing methods and deferred print calls that observe different field values.
What it assumes
Assumes familiarity with Go structs and methods while refreshing how value and pointer receivers behave.
What you can do after
Diagnose/debug with it by choosing receivers for mutation and predicting what deferred method calls will observe.
How it connects
Connects methods to value and pointer receivers, pointer copying, and deferred calls.

Also explained in

Compare how 20 books explain method →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.