Go

What's the difference between a method value and a method expression? What does this print?

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

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

func main() {
    t := T{n: 1}

    fv := t.ShowVal   // method value: receiver COPIED now
    fp := t.ShowPtr   // method value: &t captured now
    t.n = 2

    fv()              // ?
    fp()              // ?

    fe := T.ShowVal   // method expression: func(T)
    fe(t)             // ?
    (*T).ShowPtr(&t)  // method expression: func(*T)

    defer t.ShowVal() // receiver evaluated at defer time
    t.n = 3
}

Output:

val 1
ptr 2
val 2
ptr 2
val 2

A method value (t.ShowVal) binds the receiver immediately. With a value receiver, the struct is copied at that moment. With a pointer receiver, the pointer is captured, so later changes are visible. A method expression (T.ShowVal) produces a plain function that takes the receiver as its first argument.

defer and go statements evaluate the receiver and arguments immediately, so the deferred call prints 2, not 3. Method values usually allocate a closure when they escape, for example when stored in a struct field or passed as a callback.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions