Day 015 — Methods & Receivers (Value vs Pointer)¶
Month 1 · Week 3 · ⬅ Day 014 · Day 016 ➡ · Journal index
🎯 Learning Objective¶
Attach methods to types and choose correctly between value and pointer receivers, understanding how that choice affects mutation, copying, and method sets.
📚 Topics¶
- Method declaration syntax: the receiver between
funcand the name - Value vs pointer receivers · when each mutates
- Method sets · addressability · automatic
&/*by the compiler - Methods on any named type (not just structs)
📖 Reading / Sources¶
- Learning Go (Bodner) ch.7 — Methods
- Tour of Go — Methods & Pointer receivers
- Effective Go — Pointers vs. Values
- Go FAQ — Should I define methods on values or pointers?
📝 Notes¶
- A method is a function with a receiver argument:
func (c Counter) Value() int. The receiver names the type the method is bound to. - Value receiver operates on a copy — mutations do not persist. Pointer receiver operates on the original — mutations persist. This is the single most important distinction → [[value-vs-pointer-receivers]].
- Use a pointer receiver when: (a) the method mutates the receiver, (b) the struct is large and copying is wasteful, or © consistency — if any method needs a pointer, give them all pointers so the method set is uniform.
- Use a value receiver for small, immutable values (e.g. a
time.Time-like struct, coordinates). Maps, slices, channels, and funcs are reference-like, so a value receiver still "sees" shared backing data — but appending to a slice field still needs a pointer to persist a new header → [[slice-aliasing]]. - Method sets: the method set of
Tis methods with value receivers; the method set of*Tis methods with both value and pointer receivers. This matters for [[interfaces]] — a value of typeTdoes not satisfy an interface whose implementation uses a pointer receiver. - The compiler auto-takes the address (
&x) or dereferences (*p) when calling, but only if the value is addressable. A map element or the return value of a function is not addressable, som[k].PointerMethod()won't compile. - You can define methods on any named type you own, including
type Celsius float64— not just structs. You cannot define methods on types from other packages.
💻 Code Examples¶
type Counter struct{ n int }
func (c Counter) Value() int { return c.n } // value receiver: read-only copy
func (c *Counter) Inc() { c.n++ } // pointer receiver: mutates original
func main() {
c := Counter{}
c.Inc() // compiler rewrites to (&c).Inc() because c is addressable
c.Inc()
fmt.Println(c.Value()) // 2
}
Full code:
examples/month-01/methods/main.go· Run:go run ./examples/month-01/methods
🏋️ Exercises / Practice¶
| Exercise | Status | Link |
|---|---|---|
Counter with pointer-receiver Inc/Reset and value-receiver Value |
✅ | exercises/month-01/week-3/counter |
Stack push/pop showing why mutation needs * |
✅ | exercises/month-01/week-3/counter |
🐛 Mistakes Made¶
- Gave
Inca value receiver and wondered whyc.nnever changed — it mutated a copy. - Tried calling a pointer method on a map element (
scores["a"].Inc()) → "cannot call pointer method on map index expression" (not addressable).
❓ Open Questions¶
- Is there ever a correctness reason to mix value and pointer receivers on one type? (Convention says no — keep them consistent.)
🧠 Active Recall (answer without looking)¶
-
Q: Why does a value-receiver method fail to mutate the receiver?
A
The receiver is passed by value, so the method works on a *copy*; changes are discarded when the method returns. Use a pointer receiver to mutate the original. -
Q: Does a value of type
Tsatisfy an interface implemented with a pointer receiver?
A
No. The method set of `T` includes only value-receiver methods; pointer-receiver methods belong to `*T`. You'd need `&v` (and it must be addressable).
🪶 Feynman Reflection¶
A method is just a function with a hidden first argument: the receiver. If you pass that argument by value, the function edits a photocopy and your original stays untouched. If you pass it by pointer, the function edits the real thing. Everything about "value vs pointer receiver" follows from that one fact.
🕳️ Knowledge Gaps¶
- Exactly when the compiler refuses the automatic
&(addressability rules) — needs more reps.
✅ Summary¶
I can attach methods to my own types and choose value vs pointer receivers deliberately, knowing the choice controls mutation, copying cost, and which method set satisfies an interface.
⏭️ Next Steps / Prep for Tomorrow¶
- Day 016: interfaces and implicit satisfaction — and how method sets decide who implements what.
| Time spent | Difficulty | Confidence |
|---|---|---|
| 90 min | 🟦🟦⬜⬜⬜ | 🟦🟦🟦⬜⬜ |
Suggested commit: feat(examples): methods and value vs pointer receivers (day 015)