On Tue, Jun 8, 2021 at 3:16 AM Robert Engels <[email protected]> wrote:
> I like Go. A lot. I’ve designed and built systems with millions of LOC. > Pointing out aspects that might benefit from changes should be encouraged - > if not it’s a religion not a programming language. > FTR, this is the second time you are making that twist and I already called out the first and I don't appreciate that you are repeating it. "This aspect might benefit from a change" is a significantly weaker statement that using a superlative like "the most inconsistent and obtuse aspect of the Go language". > > On Jun 7, 2021, at 7:40 PM, Axel Wagner <[email protected]> > wrote: > > > > > On Tue, Jun 8, 2021 at 2:05 AM Robert Engels <[email protected]> > 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 <[email protected]> >> wrote: >> >> >> On Tue, Jun 8, 2021 at 1:26 AM Robert Engels <[email protected]> >> 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 < >>> [email protected]> 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 < >>> [email protected]> wrote: >>> >>>> On Mon, Jun 7, 2021 at 11:42 PM Robert Engels <[email protected]> >>>> 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 [email protected]. >>> 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 [email protected]. >> 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHbnJUhA0dGvS-HHBgZFHQ7VoKoDCJXsTTzjes%3DtqFsrA%40mail.gmail.com.
