What is the difference between a method value and a method expression? What does this print?
Question 38HardGo 1.22 to 1.25
type P struct{ X int }
func (p P) Get() int { return p.X }
func (p *P) Set(v int) { p.X = v }
func main() {
p := P{1}
get := p.Get // method value: a copy of p is bound NOW
set := p.Set // method value: &p is bound
f := P.Get // method expression: func(P) int
g := (*P).Set // method expression: func(*P, int)
h := (*P).Get // func(*P) int: legal, *P's method set includes Get
// _ = P.Set // compile error: invalid method expression P.Set (needs pointer receiver (*P).Set)
set(5)
fmt.Println(get(), p.X, f(p), h(&p))
g(&p, 7)
fmt.Println(p.X)
}
Output:
1 5 5 5
7
A method value, x.M, is a function with the receiver already bound. The receiver is evaluated and saved when the expression is evaluated. With a value receiver, that means a copy, so get() still returns 1 after set(5). With a pointer receiver on an addressable variable, &p is saved, so later changes are visible.
A method expression, T.M or (*T).M, turns the method into an ordinary function whose first parameter is the receiver. It follows method-set rules: (*P).Get works because the method set of *P includes value methods, but P.Set is rejected.
Where this matters:
- Passing callbacks:
http.HandleFunc("/", srv.handle)bindssrvonce. Ifhandlehas a value receiver, later changes tosrvare invisible to the handler. - Evaluating a method value on a nil interface panics immediately, at the point where you write
r.Read, not later when you call it. - A method value that escapes (stored, passed to a goroutine) allocates a closure. Method expressions don't.
- Method expressions are handy for table-driven code:
ops := map[string]func(*Stack){"pop": (*Stack).Pop}.
More on Language Fundamentals & Types
- Q36How do range-over-func iterators (Go 1.23) work? What does this print?
- Q37How do struct field alignment and padding work? What are the sizes of these structs?
- Q39What type does an untyped constant take in a non-constant shift? What does this print?