On 11/01/2017 09:31 AM, Ian Lance Taylor wrote:
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

Perhaps a small package and linter could solve this without requiring a language change. The package would expose either a NilInterface value or a IsNilInterface method. Users of the package would either compare to the pkg.NilInterface or call the pkg.IsNilInterface method. Then the linter could warn on all direct interface comparisons to nil.

Jack

--
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