On Wed, Nov 1, 2017 at 4:18 AM,  <oju...@gmail.com> wrote:
>
> Ayan, imagine I am part of a development team. In our program I have a
> pointer r:
>
> r *myType
>
> My variable r can be nil, because that is a valid situation. It is used in
> dozens of places, like this:
>
> if r != nil {
>     r.doSomething()
> }
>
> That is a very usual idiom, no only in Go, but in many languages. Every
> programmer is acquainted to that.
>
> Then, years later, other programmer in my team decides to create an
> interface to better capture a new understanding of the problem at hand,
> changing the type of r to:
>
> r myInterface
>
> Subtly, the meaning of
>
> if r != nil {
>     r.doSomething()
> }
>
> changes. Under the right circumstances our software starts to behave
> strangely. What?
>
> This problem is dangerous because it is so subtle. We will read our old code
> time and again to no avail, because everything seems fine and no one has
> changed that "if r != nil r.doSomething" in ages.
>
> As Dave Cheney said in
> https://github.com/golang/go/issues/21538#issuecomment-323561094 that could
> be solved:
>
> "by making an nil interface and an interface which contains a type who's
> value is nil also equal to nil."

A different way to state your argument is that nil is overloaded in
Go.  Your argument is essentially identical to saying suppose you have
an integer r:

type MyIntegerType int
var r MyIntegerType

and a bunch of code that tests whether r is 0 or not

if r != 0 {
    r.doSomething()
}

Then you change r to an interface type, and now the meaning of r != 0
has subtly changed.  The code still compiles, but now it means
something different.  r != 0 will be true even if the value of r
actually is 0, because in `r != 0` the `0` will be given type `int`,
but `r` is type `MyIntegerType`, so the values are not equal.

That is definitely potentially confusing, but I would like to believe
that you would not argue that we should treat r != 0 specially for
integer types.  Or, at least, we shouldn't treat it any differently
than r != 1.  And, obviously, `r == nil` should not be true if r
happens to be `0`.

I think the reason it feels different for pointer types is that we,
probably incorrectly, chose to use the same identifier, `nil`, to
represent the zero value both for pointers and for interfaces.
Suppose we had given the zero value of interface types the name
`nilinterface`.  Then the situation for pointers would be the similar
to that for integers.  Writing `r != nilinterface` would be equivalent
to `r != nil` today: it would test whether the interface itself is
nil.  `r != nil` would be a compilation error, because, unlike `0`,
there is no default type for `nil`.

If we do change something in this area for Go 2, which we probably
won't, my preference would definitely be to introduce `nilinterface`
rather than to further confuse the meaning of `r != nil`.

Ian

-- 
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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to