Mixing pointer and value receivers can be race-prone, because of the copying involved in passing value receivers.
On Mon, Oct 7, 2024 at 12:03 PM 'Axel Wagner' via golang-nuts <golang-nuts@googlegroups.com> wrote: > > To be honest, I always found this recommendation a little bit strange, > personally. > > I'll note that the standard library does not really keep to this either. For > example, time.Time.UnmarshalText (obviously) has a pointer-receiver, while > almost all other methods on time.Time have a value receiver. > And if you implement flag.Value, the Set method obviously needs a pointer > receiver, but if the String method has one as well, it won't print properly > when used as a value. In basically every implementation of flag.Value I've > ever written, String needed a value receiver, while Set needed a pointer > receiver. > > I understand the basic idea of the advice, that if a type keeps state that is > manipulated via methods, then it should generally be passed around as a > pointer, so giving all the methods a pointer-receiver works well. But if a > type *is* intended to be used as a value (like time.Time or Enum in my > example) then you will almost certainly end up with a mix of receiver kinds - > as soon as you want to add any form of de-serialization to it. So "don't mix > receiver kinds" seems like misleading advice to me. > > On Mon, 7 Oct 2024 at 19:44, Ian Lance Taylor <i...@golang.org> wrote: >> >> On Mon, Oct 7, 2024 at 10:29 AM Ken Lee <ken.lee.kiany...@gmail.com> wrote: >> > >> > --- >> > There is a consideration to make, though: historically it has been >> > considered bad form in Go to give a type a mix of value and pointer >> > receivers in methods without a very specific reason for doing so. >> > --- >> > >> > Is this still the case now? As in 2024. >> >> As a general guideline, yes. >> >> https://go.dev/wiki/CodeReviewComments#receiver-type >> >> Ian >> >> >> >> > On Sunday 13 January 2013 at 7:03:29 am UTC+8 Kevin Gillette wrote: >> >> >> >> Indeed. In addition to implicit dereferencing for value receivers, the >> >> reverse also works as well: anything that is addressable (including >> >> 'value' variables on the stack, or a field of element of anything that's >> >> addressable) will implicitly be addressed when a pointer-receiver method >> >> is called on them (though you must explicitly use the address operator >> >> when you need to pass value variables as pointers). >> >> >> >> There is a consideration to make, though: historically it has been >> >> considered bad form in Go to give a type a mix of value and pointer >> >> receivers in methods without a very specific reason for doing so. The >> >> typical justification is that a small struct in a getter method might as >> >> well have a value receiver even though the corresponding setter method >> >> uses a pointer receiver; this, however, can lead to confusion on the part >> >> of the app programmer if they start out using only the read-only methods >> >> upon what turns out to be a value-copy of the original (but hey, it >> >> compiled and seems to work, so it must be correct) -- when use of >> >> pointer-receiver methods don't seem to produce the documented changes in >> >> the original, it can be difficult to debug. >> >> >> >> >> >> On Saturday, January 12, 2013 3:17:16 PM UTC-7, Dave Collins wrote: >> >>> >> >>> On Saturday, January 12, 2013 3:52:35 PM UTC-6, Taric Mirza wrote: >> >>>> >> >>>> Thanks! Works like a charm and is helping cleaning up my code a ton. >> >>>> >> >>>> One other question, this is really more about coding style: >> >>>> >> >>>> In the case where you manipulate members of the struct, then using >> >>>> pointers as in your example is the way to go. >> >>>> >> >>>> But, you have a choice for functions that just read values from the >> >>>> struct instead of manipulating it. Is there a best practice coding >> >>>> style here, between dereferencing the struct and then using that, or >> >>>> dereferencing each member of the struct as you go? eg: >> >>>> >> >>>> // A: >> >>>> >> >>>> laser := worldobj.(*Laser) >> >>>> fmt.Printf("%0.4f,%0.4f", (*laser).x, (*laser).y) >> >>>> >> >>>> versus >> >>>> >> >>>> // B: >> >>>> >> >>>> laser := *(worldobj.(*Laser)) >> >>>> fmt.Printf("%0.4f,%0.4f", laser.x, laser.y) >> >>>> >> >>>> >> >>>> I'm kind of torn. I would imagine A) has slightly better >> >>>> performance, and doesn't require any code-rework if you later on need >> >>>> to manipulate the struct. >> >>>> >> >>>> On the other hand, B) is more readable since you don't have to look at >> >>>> pointers all over the place, just on one line. >> >>> >> >>> >> >>> Actually, you don't need to dereference at all. Go automatically >> >>> handles this for you. >> >>> >> >>> See this example: http://play.golang.org/p/ANaKaFSQLn >> >>> >> > -- >> > 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/03df7dce-5c48-44a3-bc3c-851ded2a1f08n%40googlegroups.com. >> >> -- >> 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/CAOyqgcX7v9Edk5beRH38tfJO18ZUXv-nOHsEPPCfMQy0hz%3DFdw%40mail.gmail.com. > > -- > 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/CAEkBMfGcq2nxaik_qAWoX81W-tTKRRYBDM5_6%3DefSv4tr8b03g%40mail.gmail.com. -- 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/CAMV2RqoQYRoVRB7fy%3DwUsngFjb0sJVwA39RwuO%3DYnhcWy%3Dp__A%40mail.gmail.com.