Hi, assume that method values were not promoted to pointer types. And pointer receiver methods can obviously not get promoted to value types: If you pass var v T; f(v) you don't expect `v` to be modified. But pointer methods would expect that. You'd get hard to find, confusing bugs. So the method set of a type is exactly the set of methods declared with that receiver type.
Now consider flag.Value <https://pkg.go.dev/flag#Value>. Obviously, the Set method requires a pointer receiver *T. If String would have a value receiver T, then neither T nor *T would implement flag.Value: Neither type has *both* methods. So String also needs to have a pointer receiver. But that means, if you do e.g. var t time.Time; fmt.Println(t) the String method would not get called - it would format as something like {42,23,0xdeadbeef}. The promotion of value receiver methods to pointer types means it is possible for a type to mix receiver kinds. Methods that make more sense on a value - like String - can use a value receiver, while methods that require a pointer - like Set - can still use a pointer receiver. Yes, this means the program will panic if you call String on a nil-pointer. But… well, don't do that, then. It would panic if the receiver was a pointer receiver as well, as soon as it tries to access on of the receivers fields (which it needs to do to stringify). What is a little bit confusing is, that while pointer receiver methods are not promoted to value types, you can still do var b strings.Builder; b.WriteString("foo") despite WriteString having a pointer receiver. That's because the selector expression becomes syntactic sugar for (&b).WriteString under these circumstances. Personally, I kind of feel this was a mistake, but c'est la vie. On Tue, 10 Jun 2025 at 22:06, Alexander Shopov <a...@kambanaria.org> wrote: > Does anyone have any idea why method sets were designed like this? > > Method sets of pointer types include the methods defined on the type > that the pointer points to (Explicitly pointed out in spec > https://go.dev/ref/spec#Method_sets) > > I get the idea that having a pointer means that one can mutate the > value - so in essence it may be useful to have the pointer method set > contain the value method set. > But having a pointer to a value does not guarantee the existence of value. > > Let's have a look at this trivial example: > https://go.dev/play/p/ztNRPYfoAuk > > type num interface { > > num() int > } > > type example struct{} > > func (e example) num() int { > return 42 > } > > func useNum(n num) { > fmt.Println(n == nil) > v := reflect.ValueOf(n) > fmt.Println(v.Kind() == reflect.Ptr && v.IsNil()) > fmt.Println(n.num()) > } > > func main() { > var e1 example > var e2 *example > useNum(e1) > useNum(e2) > } > > useNum has no safe way to call the num() method, even though we are > sure it is safe to call on a nil, in essence it never accesses the > state of the example struct. > However a caller can substitute a value with a pointer. Within the > useNum function we cannot guard with a n != nil since it receives an > interface and it will not be nil. > The only way to guard is with reflection. > > This same method is also used in Go standard library: > - https://go.dev/src/fmt/print.go#L592 > - https://go.dev/src/log/slog/handler.go#L564 > > So given this - is there any source on why method sets were designed this > way? > > Kind regards: > al_shopov > > -- > 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 visit > https://groups.google.com/d/msgid/golang-nuts/CAP6f5Mm1eF4XZw5sJMvrP4-sb2DkppoFuAtzbwUcbdXQyP1J8w%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 visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfH%2Bj14F0pQmaih4MqwNFvCSj23OKTyg9qH_kLipDTG2-w%40mail.gmail.com.