On Tue, Jun 8, 2021 at 2:05 AM Robert Engels <reng...@ix.netcom.com> wrote:

>
> We agree. It needs a pointer receiver to work. The atomic is also needed
> in this case for background logging.
>
> The problem in this case is that recordEvents() has to document that the
>  EventLogger passed to recordEvents() must have a pointer receiver for the
> Log() method. There is nothing in the language that allows me to declare it
> nor the compiler to enforce it.
>

It is possible to write a working implementation of that interface without
a pointer receiver - it just needs to *contain* a pointer:
https://play.golang.org/p/Xm6ASGcCyhR
You could also have a slice type, which also can do modifications without a
pointer receiver. Or a map-type. Or a channel.

If you would restrict an interface to require pointer-receiver, you would
wrongly restrict the implementer from all these possibilities.

As is the common wisdom, the user of an interface should not care what the
concrete type implementing an interface is (except if it needs to do a
type-assertions). It's the same wisdom that applies to people wanting to
check if an interface contains a nil-pointer: That check relies on the
assumption that the interface contains a pointer, which shouldn't be nil
and that's not something that should concern the user of an interface.

Again, to be abundantly clear (you still seem unwilling to acknowledge
this): The problem with your code is not the definition or usage of the
interface. It's the definition of the method that is wrong. The
interface-definition is fine and works fine.

If you don’t see this as suboptimal and an area for improvement I am not
> sure what else I can say.
>

I just want to state again, clearly, that all I objected to was you calling
this "the most inconsistent and obtuse aspect of the Go language", which I
perceived (and still do) to be an overstatement. "It is suboptimal" or "it
is an area of improvement" are both significantly weaker statements, which
I find less objectionable.

Personally, I still don't think it is a huge problem. And the fact that you
where having a lot of trouble coming up with an example showing it to be
one (the one you posted doesn't - again, it doesn't, in any way, change
behavior when using or not using interfaces) is, in my view, a testament to
that.

And by the way, linters often flag correct code - that is why they have
> disable options. They try to enforce the most common cases - and by the
> recommendation in the faq to only use receivers of the same type - it seems
> appropriate to me to have the linter flag this.
>

I'm opposed to a linter flag, because it would flag correct code I
regularly write. In general, linters should not be ignored - they either
shouldn't be run, or they should be followed. Note that golint has no
option to selectively disable a particular instance of a warning - the only
way to silence a warning is to change the code. But I don't want to use a
pointer receiver, if a value receiver is more appropriate.

If golint or go vet would start flagging this, I would likely follow the
advice it's giving. Because that's how linters and static checks are
supposed to be used - to enforce consistency. But I'd be sad doing it.
Which is why I don't want them to flag it.

I'm less opposed to the FAQ entry. Simpy because an FAQ entry can be more
easily ignored where it makes sense. If you will, it is one step in
stringency below a linter. I'm fine defending my choice in a code review,
but I don't want to defend it to a linter.


> As to this being in my opinion the most inconsistent and obtuse aspect of
> Go - that is my opinion. Curious, what do you think would take the top spot?
>

I'm not sure. I don't like putting things in absolute order or claiming
something is "the most X" for exactly that reason - it almost always turns
out to be an overstatement.

Empirically, the issue of nil-pointers in interfaces not being nil seems to
take one of the top spots, even though I don't fully understand why.
To me, concurrency in Go is extremely subtle and I would generally advice
novices to stay away from it at first (or stay with extremely simple
constructs), because they are likely to get it wrong.
Details of how Go handles constants and type-identity/assignabiity is what
is probably most often tripping me, personally, up in questions/quizzes
about Go. But it rarely comes up in practice.
The lack of co/contravariance is probably one of the things I miss the most
from the language.

It really depends on what you're asking. And I'm very likely forgetting
things while being put on the spot.
It's just a lot easier to make relative judgments, than absolute ones.


>
> On Jun 7, 2021, at 6:34 PM, Axel Wagner <axel.wagner...@googlemail.com>
> wrote:
>
> 
> On Tue, Jun 8, 2021 at 1:26 AM Robert Engels <reng...@ix.netcom.com>
> wrote:
>
>> The pattern of a background stats collector is a common one. The atomic
>> is required not optional.
>>
>
> It might be a common pattern, but it uses a pointer-receiver in that case.
> The atomic operation is not required, it operates on a local variable.
> Again, I don't understand how you can make statements that are so clearly
> wrong.
>
> Feel free to try running it in the race detector without an atomic
> operation. Feel free trying to get the race detector to trigger without the
> atomic access, but keeping it silent when you add it. You'll find that this
> needs a pointer receiver. Because otherwise the function is operating on a
> local variable.
>
>
>>
>> On Jun 7, 2021, at 6:16 PM, 'Axel Wagner' via golang-nuts <
>> golang-nuts@googlegroups.com> wrote:
>>
>> 
>> BTW, just to nail down the point of that code being wrong without
>> interfaces: Your usage of `atomic` in `Log` is superfluous. You are
>> operating on a local variable, so there is no possibility of concurrent
>> modification. Your code is equivalent to this:
>> https://play.golang.org/p/zYG0zTsk-2a
>> The only reason to use `atomic` here (and why you used it) is if that
>> memory could be shared between goroutines. For that to happen, you need a
>> pointer receiver though.
>>
>> I refuse to believe that interfaces have anything to do with this
>> obfuscation here. There is more than enough indication of it being wrong in
>> any case.
>>
>> On Tue, Jun 8, 2021 at 1:05 AM Axel Wagner <axel.wagner...@googlemail.com>
>> wrote:
>>
>>> On Mon, Jun 7, 2021 at 11:42 PM Robert Engels <reng...@ix.netcom.com>
>>> wrote:
>>>
>>>> I don’t think that represents the problem fairly. In the non interface
>>>> case I know I can’t accept a copy so I would declare the method as taking a
>>>> pointer to the struct.
>>>>
>>>
>>> How methods are declared should, in general, not be a matter of whether
>>> or not they are assigned to an interface, but to whether or not they need a
>>> pointer. Again: Your code is incorrect without interfaces
>>> <https://play.golang.org/p/WpIzYYLOKn->. The problem doesn't happen
>>> when you put that value into an interface - it happens when you pass a copy
>>> of it and expect it to refer to the original. Interfaces are just one way
>>> to create such a copy, but they do not matter for the correctness of this
>>> code and for whether or not that method needs a pointer receiver (it does).
>>>
>>> But again, to be clear: I'm not saying problems like this *never* happen
>>> and I'm not even saying that interfaces may obscure it in some cases. Just
>>> that a) the root cause here is that your method really needs to take a
>>> pointer-receiver, interfaces or not and b) that it seems very much an
>>> overstatement to me to call this "the most inconsistent and obtuse aspect
>>> of the Go language".
>>>
>>> With interfaces this is lost - as the interface is implicitly a pointer
>>>>
>>>
>>> Well, it seems a bad idea to say that interfaces are implicitly pointers
>>> then. That seems to indicate that Rob's original phrasing is indeed an
>>> important clarification - the language behaves as if the value contained in
>>> them is copied when the interface value is copied.
>>>
>>> It seems the confusion here is, that you assume it's not. And that
>>> interfaces act as a pointers, when they don't.
>>>
>> --
>> 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/CAEkBMfGVyvYYpQhCp_JkxN9EvgZ4FXJ8_WpxseJOB1OR7qt6ww%40mail.gmail.com
>> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfGVyvYYpQhCp_JkxN9EvgZ4FXJ8_WpxseJOB1OR7qt6ww%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
>> --
> 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/CAEkBMfHibUpDHQU9m8%3DrLYtnDj%3DFY01nkuP4k0Giow-hCbhNgQ%40mail.gmail.com
> <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHibUpDHQU9m8%3DrLYtnDj%3DFY01nkuP4k0Giow-hCbhNgQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
>

-- 
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/CAEkBMfHbKu7yh7sOH_vCEtSLENknixkQVCW%3DaTEZ52UuzAMOzA%40mail.gmail.com.

Reply via email to