It seems a very bad idea, to require the common case to go through some
package or else get lint-warned.

Checking "x == nil" is the correct way to check whether a value contains a
valid implementation of an interface - and a nil-pointer with the correct
method set is, as far as you should be concerned, such a valid
implementation.
If you indeed want to check whether the contained value is a nil-pointer
(I'm having actual trouble coming up with a scenario where you'd want to do
that - except cases like encoding/json, where you need to use reflection
anyway), you have to check that explicitly, either by converting nil into
the correct type (i.e. "x == (*T)(nil)"), or by type-asserting. That is the
uncommon case, so it's fine having to jump through a couple of hoops for
hat.

What *might* make more sense, is trying to lint whether a nil-pointer is
used for an interface, and the corresponding methods are not nil-safe. I.e.
do the "is a nil-pointer a valid value for this interface" check where it
belongs: At the point where the interface-conversion happens (when
assigning it to an interface-typed variable or passing it as an
interface-typed parameter).

On Wed, Nov 1, 2017 at 6:09 PM, Jack Christensen <j...@jackchristensen.com>
wrote:

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

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