* targe...@gmail.com <target....@gmail.com> [200827 05:40]:
> On Thursday, August 27, 2020 at 12:20:59 PM UTC+3 axel.wa...@googlemail.com 
> wrote:
>> I'm saying the current situation is less confusing than what you
>> describe, yes.
>>
>> AIUI, with what you describe, if I have a variable `x` of type `*T`
>> and an interface variable `y`, then `y = x` and `y = (*T)(x)` have
>> different semantics. I think it is strange to have a conversion of
>> `x` *to its own type* have any sort of semantic implication. It
>> should be a no-op.
> 
> It may be expressed in some different way. To me, if `x == nil` and then `y 
> != nil` after `y = x` is much more confusing. If you ask my opinion, I 
> would make interfaces compare to nil on just data pointer. If one wanted 
> interface which doesn't require data, he could've easily created one with 
> static stub variable. No additional checks, no "semi-nil" fat pointers, 
> everything simple and consistent.

I agree with Axel.  The `y = x` operation is a conversion, not just an
assignment.  You cannot assume that the transitive property of equality
holds where conversions are used.  Note also that both y == nil and x ==
nil involve implicit conversion, because nil is the _untyped_ zero
value, so the value being compared to y is nil converted to the
interface type, and the value being compared to x is nil converted to
the concrete type; these are _different_ zero values.

I think there are two incorrect generalizations that lead to Go
programmers having the confusion being discussed.  The first is that nil
is the "universal" zero value, which leads to the false idea that nil
of one type is the same as nil of another type.  I think when a
programmer stops to think about this, they will get the correct answer,
but often this level of detail is not brought to a high enough level of
conciousness when actually writing code.  The correct thinking is that
nil is the _untyped_ (rather than universal) zero value.  Note that you
cannot even evaluate nil == nil!

The second is thinking of an interface value containing a concrete value
as being the same thing as the concrete value.  I'm not sure why this is
such a sticking point for some, but it clearly is.  It may be for some
that they think of interfaces as a "partial generic" language feature,
such that declaring a variable of an interface type is a way to directly
use any of the types that implement that interface.  This is the wrong
way to think of it, as the interface value cannot be used in Go code in
the same was as the concrete value, except in the very specific case
where you are invoking a method on the interface value that is defined
_by the interface_.  In particular, the interface value has its own,
distinct, zero value from the zero value of the contained concrete type.

Consider the code:

type Fooer interface {
    Foo()
}

type X int

func (i X) Foo() {
}

func main() {
    var i X
    var f Fooer = i
    fmt.Println(f == 0)
}

You would not (at least you should not) expect this to compile, much
less give you the "obvious"(?) answer.  Yet, when you change

type X int
func (i X) Foo() {
...
    var i X
...
    fmt.Println(f == 0)

  to

type X struct{}
func (i *X) Foo() {
...
    var i *X
...
    fmt.Println(f == nil)

you expect that the nil is being compared to the concrete value
contained by f rather than the value of f.

If you had to explicitly convert nil to the proper type before
comparison, the problem would be much more obvious.

If you think of an interface value as a container for a concrete value,
rather than the concrete value itself, then the interface value might be
empty (nil, no concrete value) or it might contain a concrete value (not
nil, but the concrete value might be its own zero value).

As Axel said, you just have to learn that interface_value == nil
determines whether interface_value has been assigned a concrete value,
not whether the concrete value is its own zero value (which might
coincide with nil converted to the concrete type).

...Marvin

-- 
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/20200827160217.mw7tg6ef224htgxe%40basil.wdw.

Reply via email to