On Tue, 2021-06-08 at 07:57 -0500, robert engels wrote:
> The following code is works fine from the developers perspective:
>
> https://play.golang.org/p/gC1XsSLvovM
>
> The developer says, oh cool, I see this great new 3P library that
> does background logging - I want to use that instead. Hey, I already
> implement the EventLogger interface, so no problem, I take out my
> manual logging code, and make a call to recordEvents(EventLogger).
>
> Hmm, my program isn’t logging properly any more. Oh, it says
> background logging - that likely means concurrency - so maybe I have
> a race condition, so I run it under —race. Hmmm, says it's fine and
> it still isn’t working. :(
>
> Eventually the developer figures out that the call to recordEvents()
> is making a copy, and so needs pointer receiver and to create a
> pointer based interface reference (and add the atomic calls). It’s
> not clear to me how the library author would document things to avoid
> this scenario.
>
> If you don’t see that the above is suboptimal and an AFI I am not
> sure what else I can say. That a person of your caliber writes code
> that differs from the recommendation in the FAQ (the mixing of
> receiver types) is a flag to me that one of the approaches is
> probably not correct.
>
> ‘go vet’ already has the ability to disable certain checks. Adding a
> check to ‘go vet’ to detect mixed receiver types (which the FAQ says
> is not recommended) seems reasonable and will make life easier for
> many beginner Go programmers - and some seasoned ones as well :)
>
> The duplicitous and transparent nature of pointer/value receivers and
> interfaces is a source of confusion. I think being explicit would
> have been a better choice here but that horse has left the barn.


An error like this would be found in any reasonable set of tests for
the type. Minimally, if the type is intended to be passed to functions
in order to be able to be used, a test would involve that and that
would immediately surface the error.

What you seem to be asking for is a way for the language to enforce
contracts on behaviour from the source and you seem to put that at the
feet of interface handling. However, it is clearly something that
arises without needing interfaces in the language; a user of the
MyEventRecorder type would already find problems if they pass the value
to a function without needing to do that in an interface value. Without
significant addition of annotations for implementations it is not
possible for the language to understand the contractual obligations of
an implementation, and these kinds of annotations are in opposition to
the design of the language. Other languages do have these kinds of
marks, but they are not Go (thankfully).

In terms of documentation of expectations of an interface if that were
the situation, there are examples in the standard library where it's
described that implementations must be able to mutate themselves — be a
pointer receiver (or other reference-like type).


-- 
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/cce7af413d7cb56b4fd653703f1d49d6f5f7e7c6.camel%40kortschak.io.

Reply via email to