Converting nil pointer to interface yields non-nil value

3,924 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
to Glyn Normington, golang-nuts
On Fri, May 23, 2014 at 12:36 AM, Glyn Normington
<gnorm...@gopivotal.com> wrote:
>
> 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.

It makes the language less orthogonal for no clear gain.

> (Ok, converting
> nil to a string form would be a little messier, but surely there would
> be another solution for that particular problem.)

Any time a language change makes something "a little messier," you
have introduced complexity that people using the language need to
understand. Since the only purpose of the proposal seems to be
avoiding a different thing that people need to understand, there is no
clear gain here.

Ian

Glyn Normington

unread,
May 23, 2014, 9:35:19 AM5/23/14
to Ian Lance Taylor, golang-nuts
Thanks for the reply Ian. I accept that Go 1 is frozen, so I'm not
proposing a change (until perhaps Go 2). More thoughts inline.

Regards,
Glyn
On 23/05/2014 14:23, Ian Lance Taylor wrote:
> On Fri, May 23, 2014 at 12:36 AM, Glyn Normington
> <gnorm...@gopivotal.com> wrote:
>> 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.
> It makes the language less orthogonal for no clear gain.
The gain would be to prevent more users falling into this trap. The FAQ
about this behaviour could be deleted, which would be a simplification.

The current behaviour breaks the principle of least surprise , which
amounts to non-orthogonality (in a possibly different dimension).
>
>> (Ok, converting
>> nil to a string form would be a little messier, but surely there would
>> be another solution for that particular problem.)
> Any time a language change makes something "a little messier," you
> have introduced complexity that people using the language need to
> understand. Since the only purpose of the proposal seems to be
> avoiding a different thing that people need to understand, there is no
> clear gain here.
Well, I think this affects Go standard library (e.g. fmt package)
implementers more than the general user population. I'd say there would
be a net positive effect for the language.
>
> Ian

DV

unread,
May 23, 2014, 12:04:24 PM5/23/14
to golan...@googlegroups.com, Ian Lance Taylor
There's a lot of things that may "trip up" users in any language. 
Take, for example, C++. If we decided to "simplify" or "remove" features that trip up users, we'd have...........C. 

Anything that is new is potentially unexpected/interesting/weird/funny. I don't see Go's treatment of interfaces and nil being *that* funny. I was tripped up *once* by this, read the FAQ, never got tripped up again. 

Now that I understand how interfaces work (there have been excellent blog posts on the subject), your suggestion leaves a very sour taste in my mouth. They work *exactly* as they should, assuming you understand how they work. In effect, it will make *my* job more difficult, and all I gain from that is one less FAQ entry? No thanks. 

Jae Kwon

unread,
May 26, 2014, 7:21:46 PM5/26/14
to Andrew Gerrand, golang-nuts
Andrew,

This is a public apology.  In my previous comments I've made ignorant presumptions about whether you would encounter some issue in the future.
You're a significant contributor to the Go language, a language I love dearly, and your judgement in the matter of nil receivers is well justified.

For the record, I also find the current behavior of the language to be good -- a great balance between speed and simplicity.

Let us not waste any more man-years on this issue.

Regards,


Thomas Bouldin

unread,
May 26, 2014, 9:21:47 PM5/26/14
to golan...@googlegroups.com, Andrew Gerrand, jkwon...@gmail.com
I want to first concede that I understand why this behavior happens technically. I understand that Go's typesystem is stricter than most languages. I also understand that the way interfaces are implemented in Go cause this behavior; the type value of the interface is not nil in one operand and is nil in the literal "nil". I also want to concede that changing this behavior may complicate the spec; that is your area of expertise, not mine.

I'd like to instead consider this behavior from the perspective of the language consumer, not the implementer, as one would presume the former vastly outnumbers the latter. I think I have a reasonable case that from the consumer perspective, this behavior is inconsistent and an additional case where this behavior prevents desirable use cases.

The Go spec calls "nil" a "Zero Value", and the rules for conversion lay the groundwork for converting nil to an interface (which is why this is a valid, but not always true, comparison). Given that nil is called a "value" in the spec and Go's flexibility with constant value conversions, a consumer seems justified to consider the constant value comparison against nil inconsistent with other zero value comparisons.

To concede Nate Finche's point, I also code in Go full time and have done so for over a year. I also use multiple return values and errors to avoid checking whether interfaces are nil; except for the error, which is an interface. This issue bit me while building a higher-level API framework for our developers because I could not rely on the type system to enforce subtypes of errors.

Consider an API server with roughly the following:

type PublicError struct {
  Code int
  Message string
}

type (e *PublicError) Error() string {
  b, _ := json.Encode(e)
  return string(b)
}

// Presumably types can implement all CRUD interfaces.
// The point here is that implementers are forced to return documented errors in failure conditions.
type Updater interface {
  ServeUpdate(r *APIRequest)(resp *APIResponse, err *PublicError)
}

Within the framework, there will eventually be some sort of method that handles errors beyond that of PublicError (e.g. net.Error, http.ProtocolError, etc.). All code which depends on the Updater interface must forever be aware of the possibility that Update returned a nil err value, because these "error" values will fail a "== nil" check. This was quite alarming and unintuitive as a consumer. It is also seems strange that Go's strong typing is a liability here rather than an asset. I'm not suggesting that we must change the behavior of invoking a method on a nil interface, but it seem reasonable that a "zero value" should be comparable with its constant definition without using reflection.

--Thomas

Andy Balholm

unread,
May 26, 2014, 9:30:33 PM5/26/14
to Thomas Bouldin, golan...@googlegroups.com, Andrew Gerrand, jkwon...@gmail.com

On May 26, 2014, at 6:21 PM, Thomas Bouldin <thomas....@gmail.com> wrote:

> // Presumably types can implement all CRUD interfaces.
> // The point here is that implementers are forced to return documented errors in failure conditions.
> type Updater interface {
> ServeUpdate(r *APIRequest)(resp *APIResponse, err *PublicError)
> }

The problem is declaring err as *PublicError instead of the idiomatic error type.

Andrew Gerrand

unread,
May 26, 2014, 9:39:16 PM5/26/14
to Thomas Bouldin, golang-nuts, Jae Kwon
On 27 May 2014 11:21, Thomas Bouldin <thomas....@gmail.com> wrote:
I'd like to instead consider this behavior from the perspective of the language consumer, not the implementer, as one would presume the former vastly outnumbers the latter. I think I have a reasonable case that from the consumer perspective, this behavior is inconsistent and an additional case where this behavior prevents desirable use cases.

I'd like to point out that the "complexity" argument against this change is not about implementation complexity, but rather the cognitive load that such complexity places on the programmer.

When you understand how interfaces work (I recommend reading this blog post) it is easy to reason about all this stuff, and the original complaint is simply not something that comes up. If we add more subtlety to the interactions between concrete types and interface types, we force the programmer to consider that subtlety whenever they write code.

In the case of your example, your mistake is returning a concrete error type instead of an error (interface) value. Functions should always return the error type, not a concrete error type, to avoid exactly this issue. This is covered by the FAQ.

Andrew

Thomas Bouldin

unread,
May 26, 2014, 10:33:30 PM5/26/14
to Andy Balholm, golan...@googlegroups.com, Andrew Gerrand, jkwon...@gmail.com
I understand this is the technical cause of the problem, but most users would expect this to be a valid way to enforce conformity to a stricter kind of error. In this case, I was ensuring that developers would use documented errors with known error codes when they extended the service.

In this case, a literal nil is converted into a stronger type automatically because of the signature mismatch (one function returns a pointer and the other returns an interface) and then fails to compare to a literal nil. It's a very bizarre edge case in Go usage that requires a typed temporary casted as an interface. I'm quite familiar with the mechanics, but whenever I try to start a discussion about the use of the language I'm instead told I'm ignorant and "educated" how the current state exists but not why.

Andrew Gerrand

unread,
May 26, 2014, 10:58:45 PM5/26/14
to Thomas Bouldin, Andy Balholm, golan...@googlegroups.com, jkwon...@gmail.com
On 27 May 2014 12:33, Thomas Bouldin <thomas....@gmail.com> wrote:
I understand this is the technical cause of the problem, but most users would expect this to be a valid way to enforce conformity to a stricter kind of error. In this case, I was ensuring that developers would use documented errors with known error codes when they extended the service.
 
Don't do that. :-)

Go doesn't have as strong culture of "return this specific error type". That kinda defeats some of the nice properties of its interfaces, where you needn't care what the concrete type of an interface value may be.

Documentation and tests are your friends here.

In this case, a literal nil is converted into a stronger type automatically because of the signature mismatch (one function returns a pointer and the other returns an interface) and then fails to compare to a literal nil. It's a very bizarre edge case in Go usage that requires a typed temporary casted as an interface. I'm quite familiar with the mechanics, but whenever I try to start a discussion about the use of the language I'm instead told I'm ignorant and "educated" how the current state exists but not why.

It has been discussed upthread.

Basically: nil receivers have meaning (and are useful), so there is a valuable distinction between a nil interface value and an interface value contains a nil value of a concrete type. This behavior falls out of the design of the type system, methods, and interfaces respectively.

The edge case that is the topic of this thread is a subtlety that one needs to understand, but it is one that is easily reasoned about if you understand the language.

You're frustrated because your pushing against the grain of the language. When people say "don't do that" about using non-interface error returns, they are doing so for a reason.

Andrew

Kevin Gillette

unread,
May 26, 2014, 11:45:56 PM5/26/14
to golan...@googlegroups.com
An analogy: pointers are note-cards that can have an address written on them; each unique type has a unique style of note-card; a nil pointer equates to a blank card, and you can still do useful things with blank note-cards. Conversely, interface values are boxes; a nil interface value equates to an empty box. You can obviously put a blank note-card into a box: the box won't be nil, but the note-card will be. Whether you're looking at something nil depends on whether you're looking at the box itself (non-nil), or the thing in the box (which is nil).

The same could be said for *[]int (the pointer can be non-nil, yet point to a nil slice), maps, channels, function values, and other pointers. If we were to disambiguate this between interfaces and pointers (by changing nil to something unique to each type family), then we'd also have to make new 'nil' identifiers for each of the other nil-able meta-types, which isn't really a solution at all.

Jae Kwon

unread,
May 27, 2014, 12:29:07 AM5/27/14
to Thomas Bouldin, Andy Balholm, golan...@googlegroups.com, Andrew Gerrand
Here's my stab at the *why*.

* We want to be able to call methods on nil receivers because it's useful.
* This necessarily creates two kinds of nils for an interface variable -- typed nils, and untyped nils.
* It's natural for 'interfaceVariable == nil' to only return true for untyped nils.
* Besides, there's no easy way to implement a type-safe 'v (interface) == nil (pointer of some type)' without using reflection which is costly (due to dereferencing, etc).

So the only available options are either go with the established convention (e.g. return error interface values, check for nil pointers and return explicit nils, etc), or use something other than 'v == nil'.

On this node, Dan Kortzchak says:
> ... the function you want already exists - you
> can do it faster with unsafe if you want[1], though less type-safely.

> [1]http://play.golang.org/p/pp6lX_JFWP
> [2]http://play.golang.org/p/iMoFUaH-Jz

I've benchmarked both IsNil and IsZero functions.  IsNil takes roughly 15~20X more time than a simple 'v == nil', while IsZero is maybe 50% slower than a simple 'v == nil'.
If this issue bothers you so, then maybe it's worth using IsZero, defined in the first link above.  As Dan notes, it's not type-safe, but maybe a bigger issue is in compatibility between different conventions -- while using IsZero is compatible with the existing convention, the converse is not true.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

I agree with Thomas that those of us trying to discuss these finer points are being accused of being ignorant when in fact we perfectly understand the technical details.  I've tried to ignore those remarks but it's frustrating nonetheless when people accuse and talk past each other.

In retrospect, all I wanted to hear is something like what I've posted above.

Andrew Gerrand

unread,
May 27, 2014, 12:42:46 AM5/27/14
to Jae Kwon, Thomas Bouldin, Andy Balholm, golan...@googlegroups.com

On 27 May 2014 14:27, Jae Kwon <jkwon...@gmail.com> wrote:
I agree with Thomas that those of us trying to discuss these finer points are being accused of being ignorant when in fact we perfectly understand the technical details.  I've tried to ignore those remarks but it's frustrating nonetheless when people accuse and talk past each other.

It's really difficult because  people tend to see "sides" of an argument, when in reality there are many voices in the conversation with different opinions and levels of knowledge.

I apologize if I have come across as condescending at any point in this thread. That's certainly not my intention.

Andrew

Jesse McNelis

unread,
May 27, 2014, 1:00:57 AM5/27/14
to Jae Kwon, Thomas Bouldin, Andy Balholm, golan...@googlegroups.com, Andrew Gerrand
On Tue, May 27, 2014 at 2:27 PM, Jae Kwon <jkwon...@gmail.com> wrote:
> Here's my stab at the *why*.
>
> * We want to be able to call methods on nil receivers because it's useful.
> * This necessarily creates two kinds of nils for an interface variable --
> typed nils, and untyped nils.

There is the untyped nil literal, 'nil' and then there are typed
values that are nil eg. *int(nil)
Like all untyped literals(eg. 0, "somestring"), 'nil' gets it's type
from it's context.
If you compare a *int to the nil literal, then the nil is a *int(nil).
If you compare an interface{} to the nil literal then the nil is a
interface{}(nil).

> * It's natural for 'interfaceVariable == nil' to only return true for
> untyped nils.

interfaceVariable == nil will return true for nil values of that interface type.
In exactly the same way as the above *int example.

> * Besides, there's no easy way to implement a type-safe 'v (interface) ==
> nil (pointer of some type)' without using reflection which is costly (due to
> dereferencing, etc).

No need for reflect.
Just do the comparison to a nil value of the type you're interested in.

var a interface{} = *int(nil)
a == *int(nil) //true
a == interface{}(*int(nil)) //true and exactly the same comparison as
the line above.
a == interface{}(nil) // false
a = nil
a == interface{}(nil) // true
a == *int(nil) //false

benjami...@google.com

unread,
Aug 18, 2015, 4:43:01 PM8/18/15
to golang-nuts, jkwon...@gmail.com, thomas....@gmail.com, andyb...@gmail.com, a...@golang.org, jes...@jessta.id.au
Sorry to bring up an old thread.

Based on the spec's Assignability section, ISTM that assigning a (*T)(nil) value to an interface value should not be allowed (unless nil implements the interface), since (*T)(nil) is neither the predeclared identifier nil nor does it implement the interface. 

That would certainly make it easier to write functions that accept interface arguments, e.g.
func MaybeWrite(writer io.Writer) {
  if writer != nil {
    writer.Write(...)
  }
}

Thanks,
Ben

Ian Lance Taylor

unread,
Aug 18, 2015, 4:47:50 PM8/18/15
to benjami...@google.com, golang-nuts, jkwon...@gmail.com, thomas....@gmail.com, Andy Balholm, Andrew Gerrand, Jesse McNelis
On Tue, Aug 18, 2015 at 12:42 PM, <benjami...@google.com> wrote:
>
> Based on the spec's Assignability section, ISTM that assigning a (*T)(nil)
> value to an interface value should not be allowed (unless nil implements the
> interface), since (*T)(nil) is neither the predeclared identifier nil nor
> does it implement the interface.

The question is not whether nil implements the interface. The
question is whether *T implements the interface. Interfaces are
implemented by types, not values.

If *T implements the interface, then (*T)(nil) can be assigned to a
variable of the interface type.

Ian
Reply all
Reply to author
Forward
0 new messages