Skip to content
Pointer Receivers vs Value Receivers
step 1/6

Reading — step 1 of 6

Learn

~2 min readPointers and Methods

Methods in Go attach to a type via a receiver. The receiver can be a value or a pointer — and choosing wrong is one of Go's classic gotchas.

The two forms

go

(c Counter) is the value-receiver form. The method gets a copy of the struct. Mutations don't persist.

(c *Counter) is the pointer-receiver form. The method gets a pointer — mutations go through to the original.

Why this matters

go

Go automatically takes the address when you call a pointer-receiver method on an addressable value.

When to use a pointer receiver

Use *T when:

  1. The method needs to mutate the receiver — value receivers can't.
  2. The struct is large — copying is expensive.
  3. For consistency — if any method on the type uses a pointer receiver, all of them should.

Use value receiver when:

  • The type is small (an int, a small struct).
  • You don't need to mutate.
  • The type is meant to be a value type (Time, Color, Coordinate).

The map element trap

go

Map values aren't addressable — you can't get a pointer to them, so you can't call pointer-receiver methods on them directly.

Interface satisfaction

Value and pointer methods determine which type satisfies an interface:

go

If Greet had a pointer receiver, only *Dog (not Dog) would satisfy the interface.

Common mistakes

  • Calling a pointer method on a non-addressable value: e.g., someFunc().Method() where someFunc() returns a value, not a pointer.
  • Mixing value and pointer receivers on the same type — confusing for readers and risks silent bugs.
  • Pointer receivers on tiny types — copying an int via value is faster than dereferencing a pointer.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…