Step 1 of 6 · Reading · ~4 min
Learn
Pointers and Methods
Pointer Receivers vs Value Receivers
By the end you can choose between a copy and the caller's variable for a method, change structs held in a map, and predict which types satisfy an interface. In Go Fundamentals you passed *int so a function could change the caller's variable, and wrote methods that received a copy; a pointer receiver joins the two.
A receiver is a parameter
m.Add(5) works because m is a variable, so Go rewrites it to (&m).Add(5).
Pointers to structs
A constructor is a plain function, conventionally NewT, that returns a ready pointer: func NewMeter(start int) *Meter { return &Meter{units: start} }.
Choosing a receiver
Use *T when the method changes the receiver, the struct is large, or copies would be wrong; a value receiver suits small immutable things. Pick one kind per type.
The method-set rule
The method set of T holds only the value-receiver methods. The method set of *T holds both kinds. An interface is satisfied by a type whose method set has all its methods:
An interface's value has no address to hand to such a method. var _ Resetter = (*Meter)(nil) stops compiling if *Meter ever stops satisfying Resetter.
Where the pointer method is refused
Map elements have no address, because a map may move them as it grows. Either copy out, change and write back (m := bins[k]; m.Add(1); bins[k] = m), or store pointers:
Other receivers
A named non-struct type can have methods. One that grows a slice needs the pointer, because append may return a new slice to assign back through *s:
A method value is a method bound to a receiver. A pointer receiver binds the address, so later changes show:
The typed-nil trap from Interfaces returns with methods: a nil *Fault stored in an error still carries a type, so the interface is non-nil:
Return a literal nil on success instead.
Common mistakes
- A value receiver on a method that changes state. It compiles, and the total stays put, as
AddCopyleft the reading at 0. - Keeping structs by value in a map.
m[k].field = vdoes not compile, and copy-out without the write-back silently loses the change. - Using a lookup result without a
nilcheck. An unknown key yieldsnil, and the first field access panics. - Returning a nil
*Tas an interface. The caller'serr != nilis true, and the first method call that touches a field panics.
Your exercise
Build a command-driven ledger whose accounts live in a map and change through pointer-receiver methods. The starter reads and splits each line. The likeliest mistake is a lookup that changes a copy, or one that forgets an unknown name returns nil.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…