Go

When is the receiver bound for a method value? What prints?

Question 490HardGo 1.22 to 1.25
type T struct{ n int }

func (t T) Val()  { fmt.Println("val", t.n) }
func (t *T) Ptr() { fmt.Println("ptr", t.n) }

func main() {
    t := T{1}
    v := t.Val   // method value
    p := t.Ptr   // method value, receiver is &t
    defer t.Val()
    defer t.Ptr()
    t.n = 2
    v()
    p()
}

Output:

val 1
ptr 2
ptr 2
val 1

A method value such as t.Val evaluates and saves the receiver right away. With a value receiver, it saves a copy of t (n=1), so later changes are not seen. With a pointer receiver, it saves &t, so the call reads the current field (n=2).

defer works the same way. defer t.Val() copies the receiver at defer time and prints 1. defer t.Ptr() saves the pointer and prints 2. The deferred calls run LIFO after v() and p().

This matters when you pass obj.Method as a callback, for example http.HandleFunc("/", srv.handle) or go w.run(). With a value receiver, the callback works on a frozen snapshot, and any state it changes is lost.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions