On Tuesday, 10 August 2021 at 22:50:00 UTC+1 lege...@gmail.com wrote: > And I'm still a little confused here, you know when we use the struct > method directly, it is only when the function is called that the type of > receiver determines whether the passed struct is a pointer or a copied > value. But when using a function pointer, why does it decide whether to > bind a pointer or a copied value at the time of assignment, but not at the > time of function called? > > Neither is true.
In go, *all* arguments are passed by value. If the argument is a struct, then the struct is copied. If the argument is a pointer, then the pointer is copied. Ignoring methods for a moment, just consider these simple functions: func Display1(z Zoo) { ... } func Display2(z *Zoo) { ... } v := Zoo{....} Display1(v) # v is copied vp := &Zoo Display2(vp) # vp is copied These are identical, consistent behaviours. So now onto "pointer to function". You are thinking like C. In Go there is no meaningful "pointer to function", there are just "function values": https://play.golang.org/p/Q6GogYU8f Internally of course, a function value will contain some sort of pointer to the code, just as a string value contains a pointer to the string, and a slice value contains a pointer to the slice backing array. (In the latter two cases the pointer may be nil if the len or cap is zero, and the overall value is still valid). When you pass a string or a slice to a function, you are copying this structure with its embedded pointer/len/cap, These pointers are implementation details, and are not directly accessible to the user program - at least not in a "safe" way. Whether the function takes zero arguments, one or more arguments, whether those arguments are structs or pointers or chans or whatever, affects the *type* of the value and hence how you call it, but otherwise a function value is just a value. So finally we get to methods: https://play.golang.org/p/TAPCwDvxxbo If you take a method value (pf := gz.Display), you are just getting a function value, where the special first argument of the function has been bound ("curried") to some value. If the method takes a "Zoo" receiver, then the value is bound to a copy of the Zoo value. If the method takes a "*Zoo" receiver, then the value is bound to a copy of the pointer-to-Zoo value. Again, this is 100% consistent. The function always receives a copy of the value, of the type of the argument. There is just one bit of magic, which is the automatic referencing and dereferencing. Very roughly speaking: if a method takes a *Zoo but you apply it to a Zoo value, or vice versa, the value is converted from Zoo to pointer-to-Zoo or vice versa as required. But the value which is received by the method is always of the type it declares: func (z Zoo) Display() always takes a copy of a Zoo value, and func (z *Zoo) Display() always takes a copy of a pointer-to-Zoo value. The value is always copied, and this is done at the time the method value is created, not the time at which it is called (which may be never, or may be many times). -- 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/34c3fc58-4bdf-4dc0-bd13-a675be4d0f29n%40googlegroups.com.