Converting nil pointer to interface yields non-nil value

3,788 views
Skip to first unread message

Glyn Normington

unread,
Apr 16, 2014, 8:13:09 AM4/16/14
to golan...@googlegroups.com
I'm trying to understand why a nil pointer when converted to an interface produces a non-nil value.

In the following example (available in full here):

type s struct {
}
 
func (e *s) Error() string {
return "a string"
}
 
x := (*s)(nil)

y := error(x)
 
x is nil but y is non-nil, even though the underlying type (according to reflect.TypeOf) of both variables is *s.

The example is artificial, but the same conversion behaviour occurred when returning a nil pointer from a function with return type error. I was very surprised the caller of the function behaved as if there had been an error.

Is this a bug?

OpenNota

unread,
Apr 16, 2014, 8:18:36 AM4/16/14
to golan...@googlegroups.com
http://golang.org/doc/faq , search for "Why is my nil error value not equal to nil?"

steve wang

unread,
Apr 16, 2014, 8:21:13 AM4/16/14
to golan...@googlegroups.com
No, y is an non-nil error referring to a (*s)nil. 

chris dollin

unread,
Apr 16, 2014, 8:25:22 AM4/16/14
to Glyn Normington, golang-nuts
On 16 April 2014 13:13, Glyn Normington <gnorm...@gopivotal.com> wrote:
I'm trying to understand why a nil pointer when converted to an interface produces a non-nil value.

Because different nil pointers can have different types, and the
interface remembers the type of the (nil) pointer (that it is converted from):
that remembering means that the interface value isn't nil.
 
Is this a bug?

No.

(It's a mild confusion based on the overloading of `nil` to mean the
zero value for pointers of any type and for interfaces -- it's not obvious
from the text of a program that the nils are of different types.)

Chris

--
Chris "allusive" Dollin

Nate Finch

unread,
Apr 16, 2014, 9:53:14 AM4/16/14
to golan...@googlegroups.com
So, the thing is that a nil pointer can still fulfill an interface. It's a valid value that has the correct methods. Your example is actually exactly why a nil pointer should result in a non-nil interface.  *s is a type that has a method Error() string.  Thus, it fulfills the error interface.  

The only way to get a nil interface is to actually pass the keyword nil (or create a variable of the interface without assigning anything to it).

So, for example:
func GetError() error {
   s := getPointerToS()
   if s == nil {
       return nil
   }
   return s
}

The thing about Go that confuses many newbies (even myself when I was one) is that a nil pointer is not an invalid value. It's just a specific value for a specific type.  There's nothing really special about it that makes it different than any other value (except if you try to dereference it, it'll panic.

OpenNota

unread,
Apr 16, 2014, 10:41:18 AM4/16/14
to golan...@googlegroups.com

On Wednesday, April 16, 2014 8:53:14 PM UTC+7, Nate Finch wrote:
So, the thing is that a nil pointer can still fulfill an interface. It's a valid value that has the correct methods.

jkwon...@gmail.com

unread,
May 22, 2014, 2:05:02 AM5/22/14
to golan...@googlegroups.com
I get it, but I don't like it.

This keeps biting me every time I convert function declarations from returning pointers to returning interfaces.


Even without multiple return value functions, having to write an "if block" just to assign a nil to an interface value is pretty annoying, especially since there are no ternary operators.

All for what?  So we can call struct methods on nil pointers?  That can be done with a custom pointer, e.g.

type myStruct struct {}

var NilMyStruct = &myStruct{} // a special pointer

func (self *myStruct) Foo() {
    if self == NilMyStruct { ... } else { ... }
}

Is there an actual reason why it must be as it is?

Jesse McNelis

unread,
May 22, 2014, 3:25:14 AM5/22/14
to jkwon...@gmail.com, golang-nuts
On Thu, May 22, 2014 at 4:05 PM, <jkwon...@gmail.com> wrote:
> Is there an actual reason why it must be as it is?

You can call methods on a nil pointer, but not a nil interface.
There has to be a way to distinguish an interface value that doesn't
contain a value from an interface value that contains a value that is
a nil pointer.

eg.
var a interface{} = []byte(nil)
// a is a non-nil interface value that contains a nil []byte.
var b interface{}
// b is a nil interface value that contains no value.
var c interface{} = 5
// c is an interface value that contains an int, ints can't be nil.

should a == nil be true?
should b == nil be true?
should c == nil be comparable? what should it mean?

Jan Mercl

unread,
May 22, 2014, 3:53:39 AM5/22/14
to jkwon...@gmail.com, golang-nuts
On Thu, May 22, 2014 at 8:05 AM, <jkwon...@gmail.com> wrote:
> type myStruct struct {}
>
> var NilMyStruct = &myStruct{} // a special pointer
>
> func (self *myStruct) Foo() {
> if self == NilMyStruct { ... } else { ... }
> }

I don't understand the goal (shown is only the solution), however, why not

func (m *myStruct) Foo() {
if m == nil {
// ...
} else {
// ...
}
}

Why you need/use the sentinel value &NilMyStruct instead of nil in the
comparison?

-j

Jae Kwon

unread,
May 22, 2014, 4:02:54 AM5/22/14
to Jan Mercl, golang-nuts
I would like it if "var a interface{} = []byte(nil)" also set the type to be the nil in a. (See example 1)
However, to make the language consistent, you'd have to disallow calling methods on nil pointers. (See example 2)
Otherwise, you'd get different behaviors depending on whether a variable is an interface or a struct pointer, which we don't want. (See example 3)
I think this would make the language easier to use.

======== example 1 ========

var a interface{} = []byte(nil)
a == nil // i wish this were true.

======== example 2 ========

type Greeter interface {
    SayHi() string
}

type Grumpy struct {}

func (self *Grumpy) SayHi() string {
    if self == nil { // I wish this would never happen
        return "Do I exist?"
    }
    return "Go away"
}

var g Greeter = (*Grumpy)(nil)
g.SayHi() // g is a nil pointer, I wish this would throw a runtime nil pointer dereference error.

======== example 3 ========

var gPtr  *Grumpy = nil
var g Greeter = gPtr

gPtr.SayHi() // "Do I exist?"
g.SayHi() // nil pointer dereference error

Jae Kwon

unread,
May 22, 2014, 4:04:54 AM5/22/14
to Jan Mercl, golang-nuts
Oops, in example 2 I meant to say:

var gPtr *Grumpy = nil
gPtr.SayHi() // gPtr is a nil pointer, I wish this would throw a runtime nil pointer dereference error.

Jan Mercl

unread,
May 22, 2014, 4:23:48 AM5/22/14
to Jae Kwon, golang-nuts
On Thu, May 22, 2014 at 10:02 AM, Jae Kwon <jkwon...@gmail.com> wrote:
> ======== example 2 ========
>
> type Greeter interface {
> SayHi() string
> }
>
> type Grumpy struct {}
>
> func (self *Grumpy) SayHi() string {
> if self == nil { // I wish this would never happen
> return "Do I exist?"
> }
> return "Go away"
> }
>
> var g Greeter = (*Grumpy)(nil)
> g.SayHi() // g is a nil pointer, I wish this would throw a runtime nil
> pointer dereference error.

If you need an "early" panic, be explicit:

func (g *Grumpy) SayHi() string {
if g == nil {
panic(42)
}

// ...
}

However, it's not the usual approach to check the receiver like this.
If it's never used, it doesn't matter if it's nil. If it gets used,
you'll get the desired nil pointer dereference runtime error (perhaps
later).

-j

chris dollin

unread,
May 22, 2014, 4:27:27 AM5/22/14
to Jae Kwon, Jan Mercl, golang-nuts
On 22 May 2014 09:02, Jae Kwon <jkwon...@gmail.com> wrote:
I would like it if "var a interface{} = []byte(nil)" also set the type to be the nil in a. (See example 1)

======== example 1 ========

var a interface{} = []byte(nil)
a == nil // i wish this were true.

That would be deeply wrong. The value stored in a isn't
nil, /because/ it carries the type information ([]byte) as
well as the value information (nil).

Since a could hold (say) a *string or a *int, and these should
be distinguishable even when the pointer value is nil,
then at most one of those cases could be forced to be
interface{}(nil). Better that neither is.

Chris

--
Chris "allusive" Dollin

Jae Kwon

unread,
May 22, 2014, 4:35:55 AM5/22/14
to Jan Mercl, golang-nuts
If you need an "early" panic, be explicit:

        func (g *Grumpy) SayHi() string {
                if g == nil {
                        panic(42)
                }

                // ...
        }

However, it's not the usual approach to check the receiver like this.
If it's never used, it doesn't matter if it's nil. If it gets used,
you'll get the desired nil pointer dereference runtime error (perhaps
later).

Until it bites you, after refactoring your code to convert function signatures to return interfaces instead of struct pointers.

Lets say I had a function like this:

func MakeGreeter() *Greeter {
    var g *Grumpy
    ...
    return g
}
...
g := MakeGreeter()
if g != nil {
    g.SayHi()
} else {
    fmt.Println("There was no greeter")
}

Then, if you later change the function signature of MakeGreeter to return an interface Greeter, you'd better remember to change the implementation to explicitly return nil.

Jae Kwon

unread,
May 22, 2014, 4:49:12 AM5/22/14
to golang-nuts, chris dollin
(continued...)

func MakeGreeter() Greeter {
    var g *Grumpy
    ...
    if g == nil { return nil }
    return g
}

=================

> That would be deeply wrong. The value stored in a isn't
> nil, /because/ it carries the type information ([]byte) as
> well as the value information (nil). 

I'm suggesting that the type information be set to nil should the value be a nil pointer, thus making all nil values indistinguishable.

> Since a could hold (say) a *string or a *int, and these should
> be distinguishable even when the pointer value is nil, 
> then at most one of those cases could be forced to be
> interface{}(nil). Better that neither is.

You haven't explained *why* it's good or necessary to distinguish between different nil types in an interface variable.
Why must "at most one of those cases be forced to be interface{}(nil)"?


On Thu, May 22, 2014 at 1:48 AM, Jae Kwon <jkwon...@gmail.com> wrote:
(continued...)

func MakeGreeter() Greeter {
    var g *Grumpy
    ...
    if g == nil { return nil }
    return g
}

=================

> That would be deeply wrong. The value stored in a isn't
> nil, /because/ it carries the type information ([]byte) as
> well as the value information (nil). 

I'm suggesting that the type information be set to nil should the value be a nil pointer, thus making all nil values indistinguishable.

> Since a could hold (say) a *string or a *int, and these should
> be distinguishable even when the pointer value is nil, 
> then at most one of those cases could be forced to be
> interface{}(nil). Better that neither is.

You haven't explained *why* it's good or necessary to distinguish between different nil types in an interface variable.
Why must "at most one of those cases be forced to be interface{}(nil)"?

Jan Mercl

unread,
May 22, 2014, 4:54:35 AM5/22/14
to Jae Kwon, golang-nuts
On Thu, May 22, 2014 at 10:35 AM, Jae Kwon <jkwon...@gmail.com> wrote:
> Until it bites you, after refactoring your code to convert function
> signatures to return interfaces instead of struct pointers.
>
> Lets say I had a function like this:
>
> func MakeGreeter() *Greeter {
> var g *Grumpy
> ...
> return g
> }
> ...
> g := MakeGreeter()
> if g != nil {
> g.SayHi()
> } else {
> fmt.Println("There was no greeter")
> }
>
> Then, if you later change the function signature of MakeGreeter to return an
> interface Greeter, you'd better remember to change the implementation to
> explicitly return nil.

If you need a nil interface it's better to not return anything in that
interface. Or leave it unset or use myInterface(nil). In the above,
'return g' doesn't do that. Perhaps take a look at
http://play.golang.org/p/TDz1M-hSub

A common pattern is to return an explicit nil where appropriate

func foo() (someInterface, error) {
r := &someType{...}
...
if someError != nil {
return nil, someError
}

return r, nil
}

HTH

-j

Ian Lance Taylor

unread,
May 22, 2014, 4:30:19 PM5/22/14
to Jae Kwon, golang-nuts, chris dollin
On Thu, May 22, 2014 at 1:49 AM, Jae Kwon <jkwon...@gmail.com> wrote:
>
> I'm suggesting that the type information be set to nil should the value be a
> nil pointer, thus making all nil values indistinguishable.

It's hard to generalize that. Interfaces can hold values that are not
pointers.

Ian

Jae Kwon

unread,
May 22, 2014, 4:55:14 PM5/22/14
to Ian Lance Taylor, golang-nuts
I don't understand what you mean, Ian.  I'm not suggesting any changes involving non-pointer values.

I suppose you mean, for Go to know whether an interface value is a nil pointer or not, it would have to know that the value is nil AND that the type is a pointer.

But that can be derived at compile time, such that every time there is an implicit or explicit assignment from a struct pointer to an interface variable, it checks whether the value is nil (the type is known to be a pointer type).

And unless different types of nil pointers have different values (e.g. non-zero nil values? not sure why that would be), it should be easy.

Ian Lance Taylor

unread,
May 22, 2014, 6:57:23 PM5/22/14
to Jae Kwon, golang-nuts
On Thu, May 22, 2014 at 1:55 PM, Jae Kwon <jkwon...@gmail.com> wrote:
>
> I don't understand what you mean, Ian. I'm not suggesting any changes
> involving non-pointer values.

Go aims to have concepts be orthogonal. You are suggesting that
storing a pointer value in a variable of interface type should act
differently than storing a non-pointer value. You are suggesting that
pointers have a privileged zero value that is not present for some
other types. Presumably maps and channels would act like pointers
with regard to nil values, but what about slices? What about structs
that contain only pointer fields? My purpose in asking these
questions is not to find out the answer, but to point out that your
proposal makes the language more complex. Also, now storing a value
in an interface and then doing a type switch will act differently
depending on the type and the value.

Ian

Jae Kwon

unread,
May 22, 2014, 9:41:06 PM5/22/14
to Ian Lance Taylor, golang-nuts
Go aims to have concepts be orthogonal.  You are suggesting that
storing a pointer value in a variable of interface type should act
differently than storing a non-pointer value. You are suggesting that
pointers have a privileged zero value that is not present for some
other types.

The Nil pointer is already special in various regards.
 
Presumably maps and channels would act like pointers
with regard to nil values, but what about slices?

var a []byte = nil
var b interface{} = a
b == nil // true
var c interface{} = append(nil, 1) // [1]
var d interface{} = append(b, 1) // [1]

No reason why this couldn't work.
 
What about structs that contain only pointer fields?

What about them?
 
Also, now storing a value in an interface and then doing a type switch will act differently
depending on the type and the value.

No, I'm not suggesting that we keep the type for nil interface values, but rather remove them upon assignment.

var f *Foo = nil
var a interface{} = f

switch a.(type) {
case *Foo:
    // this doesn't happen if a is nil
case nil:
    // this happens instead
}
 
My purpose in asking these questions is not to find out the answer, but to point out that your
proposal makes the language more complex.

First lets figure out the answer.  So far I don't see how it would make the language any more complex.
 

Ian

Andrew Gerrand

unread,
May 22, 2014, 9:47:33 PM5/22/14
to Jae Kwon, Ian Lance Taylor, golang-nuts
On 23 May 2014 11:41, Jae Kwon <jkwon...@gmail.com> wrote:
So far I don't see how it would make the language any more complex.

Think about how this would be described in the language specification.
You'd have to add, not take away. That, by definition, is more complexity.

What surprises me is that this is such a problem for you.
It's not something that I see in my own code, and not in the other code that I read.

In your original post you provided this code snippet http://play.golang.org/p/7XHW8s5y3Q and described problems when converting functions.

But why, in your example, would getMultiple1 return a concrete type while getMultiple2 returns an interface type?
And, as is the case of most functions that return errors, why are you not checking the error value of the function call?

It's easy to produce synthetic examples to demonstrate a pathological case. I would like to see real instances of this issue. It's much more profitable to discuss real code than demo code.

Andrew

Jae Kwon

unread,
May 22, 2014, 10:09:47 PM5/22/14
to Andrew Gerrand, golang-nuts
Think about how this would be described in the language specification.
You'd have to add, not take away. That, by definition, is more complexity.

Actually it's the other way around.  For example, see this under "Selectors":
  1. If x is of pointer type and has the value nil and x.f denotes a struct field, assigning to or evaluating x.f causes a run-time panic.
  2. If x is of interface type and has the value nilcalling or evaluating the method x.f causes a run-time panic.
With my proposed changes, the distinction goes away.
Furthermore, in the FAQ, the question "Why is my nil error value not equal to nil?" goes away.
Even the FAQ admits that the "situation can be confusing"

What surprises me is that this is such a problem for you.
It's not something that I see in my own code, and not in the other code that I read.

I've been coding in Go for over a year and I've just encountered it.  It's not "such" a problem for me, I'm merely suggesting an improvement to the language.
You'll bump into it too eventually while refactoring your code, changing method signatures to return an interface type instead of a struct pointer.

Let's just say that this thread has surprised me as well.

Regards.

Andrew Gerrand

unread,
May 22, 2014, 10:16:40 PM5/22/14
to Jae Kwon, golang-nuts
On 23 May 2014 12:09, Jae Kwon <jkwon...@gmail.com> wrote:
Think about how this would be described in the language specification.
You'd have to add, not take away. That, by definition, is more complexity.

Actually it's the other way around.  For example, see this under "Selectors":
  1. If x is of pointer type and has the value nil and x.f denotes a struct field, assigning to or evaluating x.f causes a run-time panic.
  2. If x is of interface type and has the value nilcalling or evaluating the method x.f causes a run-time panic.
With my proposed changes, the distinction goes away.

But it is fine to call methods with a nil receiver.

With your change the distinction remains, but it is now obscured by the language since you can't test if i == nil before calling the method. (I guess you could do a type assertion first... but then you need to know all possible concrete types that might implement the method.)

Furthermore, in the FAQ, the question "Why is my nil error value not equal to nil?" goes away.
Even the FAQ admits that the "situation can be confusing"

We're not optimizing the language for fewer FAQs. Everyone has questions when they learn new things. That's not a bad thing.
 
What surprises me is that this is such a problem for you.
It's not something that I see in my own code, and not in the other code that I read.

I've been coding in Go for over a year and I've just encountered it.  It's not "such" a problem for me, I'm merely suggesting an improvement to the language.

You're getting push back because language changes should not be made lightly. That you have only just discovered the issue after a year suggests it's probably not worth doing much about.

You'll bump into it too eventually while refactoring your code, changing method signatures to return an interface type instead of a struct pointer.

Will I? It's been more than four years...

Andrew

Dan Kortschak

unread,
May 22, 2014, 10:19:33 PM5/22/14
to Jae Kwon, Ian Lance Taylor, golang-nuts
On Thu, 2014-05-22 at 18:41 -0700, Jae Kwon wrote:
> > Also, now storing a value in an interface and then doing a type
> switch
> > will act differently
> > depending on the type and the value.
> >
>
> No, I'm not suggesting that we keep the type for nil interface values,
> but rather remove them upon assignment.
>
> var f *Foo = nil
> var a interface{} = f
>
> switch a.(type) {
> case *Foo:
> // this doesn't happen if a is nil
> case nil:
> // this happens instead
> }

This change would prevent you from calling a method on a nil value.
Something that is currently legal and used.

Dan Kortschak

unread,
May 22, 2014, 10:34:25 PM5/22/14
to Jae Kwon, golang-nuts
But it's useful as well as used. For what gain?

On Thu, 2014-05-22 at 19:31 -0700, Jae Kwon wrote:
> Yeah, precisely. I'm suggesting a backwards incompatible change.

Jae Kwon

unread,
May 22, 2014, 10:53:18 PM5/22/14
to Dan Kortschak, golang-nuts
To make the language simpler (e.g. remove a point of confusion, make refactoring easier)

I agree that calling methods on nil receivers is used, but I'm not convinced that it's useful.
That is, it seems that for every use of calling a method on a nil receiver, there's an equally good way of doing it differently.

The biggest reason *not* to go with my proposal AFAIK is that it's a breaking change to the language, and that's a good reason.

I'm curious if there are any other reasons.

Dan Kortschak

unread,
May 22, 2014, 10:59:05 PM5/22/14
to Jae Kwon, golang-nuts
On Thu, 2014-05-22 at 19:53 -0700, Jae Kwon wrote:
> That is, it seems that for every use of calling a method on a nil
> receiver, there's an equally good way of doing it differently.

Examples?

Jae Kwon

unread,
May 22, 2014, 11:11:28 PM5/22/14
to golang-nuts
> Examples?

You'd have to provide an example for me to provide the counterexample.

Anyways, maybe a more palatable suggestion is to have a new operator that does what I want.  This would be backwards compatible.
The new operator should work on both struct pointers and interface variables.

var a *Foo = nil
var b interface{} = a
var c interface{} = nil

nil(a) // true
nil(b) // true
nil(c) // true

Then I'd prefer to use this instead of != nil or == nil, as it would make refactoring easier / less error prone.

Dan Kortschak

unread,
May 22, 2014, 11:20:06 PM5/22/14
to Jae Kwon, golang-nuts
Here you go http://play.golang.org/p/PB54deNa46

Explodes when the value of the interface is not a chan, func, interface,
map, pointer or slice. What would you do there?

Jesse McNelis

unread,
May 22, 2014, 11:42:13 PM5/22/14
to Jae Kwon, golang-nuts
On Fri, May 23, 2014 at 1:11 PM, Jae Kwon <jkwon...@gmail.com> wrote:
>> Examples?
>
> You'd have to provide an example for me to provide the counterexample.
>
> Anyways, maybe a more palatable suggestion is to have a new operator that
> does what I want. This would be backwards compatible.
> The new operator should work on both struct pointers and interface
> variables.
>
> var a *Foo = nil
> var b interface{} = a
> var c interface{} = nil
>
> nil(a) // true
> nil(b) // true
> nil(c) // true

So that solves your specific misunderstanding about interface
comparisons with various types of nil values.
But what about this? does this surprise you?
http://play.golang.org/p/OMVNs_OkmZ

What makes nil pointers special that they should be comparable without
type information?
I would be pretty weird for comparison interfaces containing nil
pointers of different types to be equal.

Andrew Gerrand

unread,
May 22, 2014, 11:53:18 PM5/22/14
to Jae Kwon, golang-nuts

On 23 May 2014 13:11, Jae Kwon <jkwon...@gmail.com> wrote:
Anyways, maybe a more palatable suggestion is to have a new operator that does what I want.

This is getting crazy. You've encountered this problem once in a year and now you're saying you want a new operator?

This has come up before (search the list). Many person-years have already been spent thinking about this specific issue.

Let's move on.

Andrew

Jae Kwon

unread,
May 23, 2014, 12:53:09 AM5/23/14
to Jesse McNelis, golang-nuts
> What makes nil pointers special that they should be comparable without type information?

As it is, nothing.
As a hack you could fit in an extra bit of information in the interface variable, in the least significant bit of the type pointer, set to 1 if the type is a pointer and 0 otherwise.
Then, if the type pointer's least significant bit is set AND the value is zero, then you know you have a nil pointer.

Jesse McNelis

unread,
May 23, 2014, 3:06:30 AM5/23/14
to Jae Kwon, golang-nuts
On Fri, May 23, 2014 at 2:53 PM, Jae Kwon <jkwon...@gmail.com> wrote:
>> What makes nil pointers special that they should be comparable without
>> type information?
>
> As it is, nothing.
> As a hack you could fit in an extra bit of information in the interface
> variable, in the least significant bit of the type pointer, set to 1 if the
> type is a pointer and 0 otherwise.
> Then, if the type pointer's least significant bit is set AND the value is
> zero, then you know you have a nil pointer.

You're missing the point.
An interface value already has an entire word to store it's type
information. But that's not the issue.

All comparisons against interface values compare the type and value
contained within it, that is the value on the right is converted to be
an interface value for the comparison.

interface{}(5) == 5 is true because the 5 is automatically converted
to an interface{}(5) for the comparison.
interface{}(nil) == interface{}(nil) is true, because they are both
already interface values.
interface{}(nil) == nil is true because the nil is an interface value
in the same way that the 'nil' in *int(nil) == nil is an *int(nil) for
the comparison.

Your confusion results from you expecting interface{}(*int(nil)) ==
interface{}(nil) to be true.
This comes about because you assume that when you're doing
interface{}(*int(nil)) == nil that the 'nil' is an *int and not an
interface{}.
Curiously you don't have any expectation that the 'nil' in *int(nil)
== nil would be anything other than *int(nil) and the implicit type of
the 'nil' isn't at all confusing for you.

Adding an nil() function that compares against the value contained
within an interface value as well as the interface itself only helps
continue the confusion resulting in an FAQ entitled "what is the
difference between using nil() and comparing against nil with
interfaces?"

Glyn Normington

unread,
May 23, 2014, 3:36:48 AM5/23/14
to golang-nuts
Before we move on, I'll re-iterate my earlier question as I think
recording the definitive answer would be useful for everyone's
understanding:

What would have been the downside of treating an interface with a nil
value like a nil
pointer? The semantics would be that it would compare equal to nil and
would panic if you tried to use it to call a method. (Ok, converting
nil to a string form would be a little messier, but surely there would
be another solution for that particular problem.)
> --
> You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/s8kK700U8zw/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Regards,
Glyn

Volker Dobler

unread,
May 23, 2014, 5:05:18 AM5/23/14
to golan...@googlegroups.com
Am Freitag, 23. Mai 2014 09:36:48 UTC+2 schrieb Glyn Normington:
[...]

What would have been the downside of treating an interface with a nil
value like a nil
pointer?
 
It breaks existing code. 
It adds an unnecessary special case to the type system, method  invocation,
equality testing, the specification and documentation. (Maybe even more)
Everybody has to relearn what interface values are and how they behave.

V.

P.S. IMHO everybody get bitten by this once. But fortunately only once;
then you look closer at interface values and you understand interface
values and you coded happily ever after.

Jae Kwon

unread,
May 23, 2014, 6:33:10 AM5/23/14
to golang-nuts
On Thu, May 22, 2014 at 9:53 PM, Jae Kwon <jkwon...@gmail.com> wrote:
> What makes nil pointers special that they should be comparable without type information?

As it is, nothing.
As a hack you could fit in an extra bit of information in the interface variable, in the least significant bit of the type pointer, set to 1 if the type is a pointer and 0 otherwise.
Then, if the type pointer's least significant bit is set AND the value is zero, then you know you have a nil pointer.

For the record, a much better way of encoding an extra bit of information in the type pointer of an interface variable is to order the types in memory.
So for example, given a set of types such that var a interface{} = (type_i, 0x00..00) implies that a is a nil struct pointer, (vs say, a numeric type where a 0x00..00 value isn't nil but the number Zero), you can allocate them in memory above all the types.
Then, the non-reflect nil() function can first perform an inequality on the type pointer before comparing the value to zero.

That would require at most two operations, an order or two faster than using the reflect method.

Nate Finch

unread,
May 23, 2014, 7:13:03 AM5/23/14
to golan...@googlegroups.com
I think there's a point that has been lost here... 

I write Go 40+ hours a week, and I almost never write code that checks if pointers or interfaces (other than errors) are nil.

Why?  Because Go has multiple returns:

func GenerateThing() (Thing, error) {
  p, err := GetConcreteImpl() 
  if err != nil {
    return nil, err
  }
  return p, nil
}

Most of the time, this is the code I write - I don't ever check if p is nil, because GetConcreteImpl is guaranteed to return a non-nil pointer as long as err is nil. If err is non-nil, I know there was a problem, and I pass it up with a nil interface... but anyone calling this shouldn't check for nil against the interface either, they should just check the error.

Yes, very occasionally you have to write

if p == nil {
    return nil
}

This kind of thing bites everyone once (myself included)... and then they figure it out and move on.

Check out my blog post on interfaces, understanding the underpinnings may help understand why the work as they do.   I even have a whole section on nil pointers.  http://blog.natefinch.com/2014/05/intro-to-go-interfaces.html




On Wednesday, April 16, 2014 8:13:09 AM UTC-4, Glyn Normington wrote:
I'm trying to understand why a nil pointer when converted to an interface produces a non-nil value.

In the following example (available in full here):

type s struct {
}
 
func (e *s) Error() string {
return "a string"
}
 
x := (*s)(nil)

y := error(x)
 
x is nil but y is non-nil, even though the underlying type (according to reflect.TypeOf) of both variables is *s.

The example is artificial, but the same conversion behaviour occurred when returning a nil pointer from a function with return type error. I was very surprised the caller of the function behaved as if there had been an error.

Is this a bug?

Ian Lance Taylor

unread,
May 23, 2014, 9:23:59 AM5/23/14