That's a really good question, IMO. I have been wondering for a while why the advice against mixing pointer and value receivers, which GoLang so often flags me for doing.
Ideally I think that I would like to be able use value receivers most of the time when I want the method to leave the state unmodified, and only use pointer receivers when I want state to be modified. And, I don't want to have to ignore GoLand's warnings or have a CI/CD linter warn me about it considering that I want to do it on purpose. I could turn off the warning in GoLand, but that doesn't change coding standards on teams I might work on who religiously follow the Go team's recommendations. Given this thread I finally did some research. Tracking it down in the Go FAQ <https://go.dev/doc/faq#methods_on_values_or_pointers> it says: *> Next is consistency. If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used. See the section on method sets <https://go.dev/doc/faq#different_method_sets> for details. * Tracking down method sets it says *(abridged):* > *the method set of a type T consists of all methods with receiver type T, while that of the corresponding pointer type *T consists of all methods with receiver *T or T. That means the method set of *T includes that of T, but not the reverse.* *> This distinction arises because if an interface value contains a pointer *T, a method call can obtain a value by dereferencing the pointer, but if an interface value contains a value T, there is no safe way for a method call to obtain a pointer. (Doing so would allow a method to modify the contents of the value inside the interface, which is not permitted ...)* *> Even in cases where the compiler could take the address of a value to pass to the method, if the method modifies the value the changes will be lost in the caller. ... This is almost never the desired behavior.* I decided to so some experimentation and turns out it a compile error occurs when a value variable is used with a pointer receiver: - https://goplay.tools/snippet/_AiFRsc9w-r There are six (6) permutations of an interface and the variable of the interface type, two (2) of which will not compile: 1. A value variable and multiple value receivers <--- compiles 2. A pointer variable and multiple value receivers <--- compiles 3. A pointer variable and multiple pointer receivers. <--- compiles 4. A value variable and multiple pointer receivers. <--- will NOT compile 5. A pointer variable and mixed value+pointer receivers <--- compiles 6. A value variable and mixed value+pointer receivers. <--- will NOT compile Permutation #4 and #6 are consistent with the description above, and they both have *a value variable *in common. However, given than #5 DOES compile, I was left wondering why the standard that mixed receivers should be flagged as an error? I ask rhetorically — or better yet, to the Go team — shouldn't mixed receivers be considered acceptable, especially when they would allows ensuring the receiver is not changed by the method that should not change it? And then shouldn't the guidance in the FAQ be to use *value* receivers unless the receiver needs to be modified within the method? I do get that changing the guidance could violate the conceptual purity of the *"method set <https://go.dev/doc/faq#different_method_sets>"* definition, but pragmatically is being able to mix receiver types not more useful in practice? If the developer makes a mistake and passes a non-pointer interface value to a method with a pointer receiver they will get a compile error, so there does not appear to be any downside for changing the recommendation regarding consistency with method receivers? Or is there something really obvious I am just missing? -Mike On Monday, November 13, 2023 at 4:49:56 PM UTC-5 Brad Johnson wrote: > Google's style guide is a popular reference for Go programmers. In it, > they list off a number of scenarios where one would use a value receiver vs > a pointer receiver. But, ultimately, they end the list with "when in doubt, > use a pointer receiver". > > In my experience, I've noticed the majority of Go programmers I encounter > default to using pointer receivers in all circumstances. And I have a hard > time justifying any protest because the scenarios typically don't fall into > the "approved" set where value receivers are recommended. > > I also notice that my IDE (GoLand) defaults to returning a pointer to a > struct when I use its "Generate Constructor" auto-complete functionality. I > can't help but suspect this was motivated by the "when in doubt" advice > from Google. > > I'd be curious to hear thoughts on this topic. I tend to advise developers > to default to value receivers because I perceive benefits to avoiding nil > pointer exceptions. But it's hard to substantiate my advice as anything > idiomatic. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3aadebb4-68ef-43ed-8c10-d7531fb576f6n%40googlegroups.com.