Methods and pointer type receivers

117 views
Skip to first unread message

Deiter

unread,
Feb 27, 2021, 10:03:19 PM2/27/21
to golang-nuts
Go: go1.15.8 darwin/amd64
OS: MacOS 11.2.1

The program here includes a type and a method that acts on that type:

type Prefix struct {
    prefix string
}

func (rec *Prefix) outputString(s string) {
    fmt.Printf("%v: %v\n", rec.prefix, s)
}

Very straightforward. I expected that this would work too:

type PrefixPtr *Prefix
func (rec PrefixPtr) outputString(s string) {
   fmt.Printf("%v: %v\n", rec.prefix, s)
}

But it led to:
# receiver
./receiver.go:24:6: invalid receiver type PrefixPtr (PrefixPtr is a pointer type)
./receiver.go:30:10: prefixer.outputString undefined (type PrefixPtr has no field or method outputString)

I understand that golfing doesn’t have implicit type conversions, and that PrefixPtr is not the same as *Prefix, so I guess what I’m asking is twofold:
  1. Why can’t receivers be a pointer type?
  2. Why isn’t *Prefix considered a pointer type?

Kurtis Rader

unread,
Feb 27, 2021, 10:21:04 PM2/27/21
to Deiter, golang-nuts
On Sat, Feb 27, 2021 at 7:03 PM Deiter <hwate...@gmail.com> wrote:
  1. Why can’t receivers be a pointer type?

They can be a pointer type. See, for example, https://tour.golang.org/methods/8.  Also, as I write this the https://play.golang.org/p/rmnIexAGU-O you provided works.

--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

Ian Lance Taylor

unread,
Feb 27, 2021, 10:27:23 PM2/27/21
to Deiter, golang-nuts
On Sat, Feb 27, 2021 at 7:03 PM Deiter <hwate...@gmail.com> wrote:
>
Because the language supports pointer methods, as in

func (p *S) Set(...) { ... }

That is a pointer method on the type S, and it can only be called on
values of type *S or addressable values of type S. If a receiver type
could be a type defined as a pointer type, it would be confusing
whether methods declared on that type were pointer methods or value
methods. And it would be confusing whether it were valid to declare a
method on a pointer to that pointer type. We avoid those potential
confusions by simply forbidding methods on types defined as pointer
types. This does not cause any loss of functionality.

> Why isn’t *Prefix considered a pointer type?

It is, but a method defined with a receiver type of *Prefix is a
pointer method of Prefix. That method can be called on any value of
type *Prefix and also on any addressable value of type Prefix.

Ian

Howard Waterfall

unread,
Feb 28, 2021, 11:12:31 AM2/28/21
to Ian Lance Taylor, golang-nuts

Thanks Brian. It sounds like golang made it illegal to define methods on a defined pointer type for readability/disambiguation reasons rather than some fundamental, underlying technical issue. Frankly the confusion it eliminates still isn’t entirely clear to me. Given that names in general don’t confer whether something is a variable, type or interface, there are plenty of opportunities for confusion, so why single this one out? "Because you can" may be the answer. Lack of experience is likely the biggest obstacle in my understanding. I'm hopeful it’ll become more obvious along the way. I appreciate your insights.


On Sun, Feb 28, 2021 at 5:23 AM Ian Lance Taylor <ia...@golang.org> wrote:
On Sat, Feb 27, 2021 at 9:12 PM Howard Waterfall <hwate...@gmail.com> wrote:
>
> Thanks Ian! Some comments inline.

Please write to the mailing list, not just to me.  Thanks.
> Given that PrefixPtr is defined:
>
> type PrefixPtr *Prefix
>
> I'm not seeing how this:

>
> func (rec PrefixPtr) outputString(s string)
>
> is any more ambiguous than this:

>
> func (rec *Prefix) outputString(s string)

In the latter, the method is clearly associated with Prefix, and
applies to addressable values of type Prefix.  In the former, it's not
clear whether the method applies to addressable values of type Prefix.
One could make an argument either way.


> It's definitely possible that I'm being pig headed tho! Is it the asterisk that makes it clear it's a pointer?

>
>>
>> > Why isn’t *Prefix considered a pointer type?
>>
>> It is, but a method defined with a receiver type of *Prefix is a
>> pointer method of Prefix.  That method can be called on any value of
>> type *Prefix and also on any addressable value of type Prefix.
>
>
> My question arose from the error that was generated:

>
> ./receiver.go:24:6: invalid receiver type PrefixPtr (PrefixPtr is a pointer type)
>
>
> It seems to suggest that receivers can't be a pointer type. Since an error isn't generated with *Prefix, I inferred it wasn't considered a pointer type.

You can't define a method on a defined pointer type.  You can define a
method on a pointer to a defined non-pointer type.

Ian
Reply all
Reply to author
Forward
0 new messages