Vì method set của T chỉ gồm method có value receiver, còn method set của *T gồm cả hai.
Nếu interface đòi một method khai báo trên *T thì chỉ con trỏ mới thỏa mãn.
type Store interface{ Save() error }
type Repo struct{ n int }
func (r *Repo) Save() error { r.n++; return nil }
var s Store = Repo{} // lỗi biên dịch: Save has pointer receiver
var ok Store = &Repo{} // đúngLý do sâu hơn: gọi r.Save() trên biến addressable, compiler tự thêm &r. Nhưng giá trị nằm trong interface là bản sao không addressable, không lấy địa chỉ được, nên Go từ chối ngay lúc biên dịch thay vì cho sửa một bản sao rồi mất thay đổi.
Cách chọn receiver:
- Dùng pointer receiver khi method sửa state, hoặc struct lớn, hoặc chứa sync.Mutex (copy mutex là lỗi, go vet báo).
- Dùng value receiver cho kiểu nhỏ, bất biến (time.Time).
- Nhất quán trong cùng một kiểu — trộn hai loại làm method set khó suy luận và dễ dính đúng lỗi trên.
Mẹo kiểm tra tại thời điểm biên dịch: var _ Store = (*Repo)(nil).