Pointer or value receiver: which one is better?
A couple of years ago, I was consulting for a company that used PHP and was starting to use Go, and one of the first questions I got during our first meeting was: How should we define struct methods: on pointer or value receivers?
I remembered that question recently while joining another project where the team has a rule to prefer value receivers over pointer receivers. The info I got was somewhere along the lines:
We try to avoid a pointer receiver unless it’s really needed for state changes.
So I wanted to write a short article to clear up the confusion among developers, whether they are new to Go or experienced, about this topic.
A short recap
If you define a struct in Go, you can have either value receivers or pointer receivers for its methods:
type Alice struct {
}
func (a Alice) Speak() {
fmt.Println("hi, I'm Alice")
}or:
type Alice struct {
}
func (a *Alice) Speak() {
fmt.Println("hi, I'm Alice")
}A receiver is just a way of grouping methods around a struct. Besides that, it behaves exactly like a function parameter. So above are equivalent to:
func Speak(a Alice) {
fmt.Println("hi, I'm Alice")
}or
func Speak(a *Alice) {
fmt.Println("hi, I'm Alice")
}Which way is better?
Methods can be defined for either pointer or value receiver types.
Coming from a typical OOP language like PHP, you usually have a class with some methods defined on it.
Get Andrei Boar’s stories in your inbox
Join Medium for free to get updates from this writer.
You arrive at Go, keeping the same class-with-methods mental model: you create a struct, then you need to define methods for that struct. And now you’re confused because you need to decide which type of receiver to pick.
My advice is to start thinking in terms of types with methods rather than a struct with methods. You can have either T or *T, and they are two different things. They start from the same struct T, but ultimately they are two different types and two different solutions for different problems.
When in doubt, use a pointer receiver
Returning to the question of which one to choose, I consider the authoritative answer on this topic to be the Receiver Type section from CodeReviewComments, which is a collection of the most common code review comments on Go projects.
In that section, the fact that pointer receivers should be the default when you are in doubt is mentioned twice:
If in doubt, use a pointer, but there are times when a value receiver makes sense, usually for reasons of efficiency, such as for small unchanging structs or values of basic type
….
Finally, when in doubt, use a pointer receiver.
This provides a safe default, but it ultimately depends on how you plan to use your type.
If you need to modify it, if the struct is large, or if you want to avoid copying (see this article from Dave Cheney), use a pointer receiver.
If you deal with a value object or you want immutability, use a value receiver.
I suggest you bookmark that page and come back to it whenever you are in doubt.
Conclusion
I don’t want you to leave this article with another rule that you need to use pointer receivers at first.
Leave it with the idea that it doesn’t make sense to have a rule for it, and always consider how you are going to use your new type. And if, for some reason, you don’t know, then choosing a pointer receiver is usually safer.
So if it’s safer, why do some programmers choose to define methods on value receivers? This will be revealed in a future article, but I give you a hint: it has something to do with interfaces. And plot-twist: I was part of that team when they made that decision.
Happy coding!







