Go

What does this print? (defer with value vs pointer receivers)

Question 17HardGo 1.22 to 1.25
type T struct{ name string }

func (t T) ValPrint()  { fmt.Println("val:", t.name) }
func (t *T) PtrPrint() { fmt.Println("ptr:", t.name) }

func main() {
	t := T{"a"}
	defer t.ValPrint()
	defer t.PtrPrint()
	t.name = "b"
}

Output:

ptr: b
val: a

The receiver counts as an argument, so it is evaluated when the defer statement runs. For ValPrint, the method value t.ValPrint takes a copy of t at that moment (name = "a"). For PtrPrint, Go automatically takes &t, and that pointer is what gets saved. When the call finally runs, it sees the updated field. LIFO order puts the pointer version first.

The same rule applies to method values in general: f := t.ValPrint binds a copy right away. This leads to a well-known bug with sync.Mutex. If a type that contains a mutex has a method with a value receiver, that method's x.mu.Lock() and defer x.mu.Unlock() act on a copy of the mutex, so nothing is actually protected. go vet's copylocks check flags locks passed by value. What the interviewer wants to hear: a method value binds its receiver immediately.

More on Language Fundamentals & Types

All 39 Language Fundamentals & Types questions