comparing interface to nil

4,630 views
Skip to first unread message

Tom Vogel

unread,
May 7, 2012, 12:55:23 PM5/7/12
to golan...@googlegroups.com
In this contrived example:

http://play.golang.org/p/uVOq8hq5Jn

in Storage's implementation of Find it returns the result of calling a
function that returns a pointer to a type that satisfies the User
interface. But when you compare the result with nil, it says it is
not nil (even though the underlying pointer is nil).

For AnotherFind, it checks the result of calling the function and
returns nil if the result is nil, and this works.

I assume that this is because of the implicit type being returned by
Find when it returns the result of lookup and the explicit type
returned by AnotherFind when it returns nil.

My question is: what is the best way to compare an interface to nil?
I'd prefer to write my code like the Find function and not like the
AnotherFind function. But I'd like to be able to compare the result
with nil...

Thanks,

Tom

Kyle Lemons

unread,
May 7, 2012, 1:16:11 PM5/7/12
to Tom Vogel, golan...@googlegroups.com
The simplest solution by far is to never store a nil value into an interface, because that makes the interface itself non-nil and checking if the stored value is nil is nontrivial.  My justification for this is as follows: if you store something in an interface, you expect to be able to call the appropriate methods on it without caring about the concrete type.  Therefore, storing a nil pointer to a type (whose pointer-receiver methods do not explicitly handle the nil receiver case) is a semantic violation of this concept.

Tom Vogel

unread,
May 7, 2012, 1:27:10 PM5/7/12
to Kyle Lemons, golan...@googlegroups.com
Ok, that sounds reasonable. My main reason for using "nil" is to
communicate "not found" when the value is nil and the error is nil.
(for simplicity in my example, I left out the error return value)

What would you suggest instead? I could add a found flag:

type Finder interface {
Find(id int) (user User, found bool, err error)
}

which would work, but having three return values makes it a little
more complicated for the implementers.

Thanks,

Tom

chris dollin

unread,
May 7, 2012, 1:29:50 PM5/7/12
to Tom Vogel, Kyle Lemons, golan...@googlegroups.com
I think I just sent Kyle a message that was intended to go to the list.
(Did they move the reply-to-all button recently?).

Sorry, Kyle.

If it's conveneient could you forward it back to the list? otherwise I will
do sent-mail magic later ...

Chris

--
Chris "allusive" Dollin

Kyle Lemons

unread,
May 7, 2012, 1:31:00 PM5/7/12
to chris dollin, golang-nuts
Chris,
  Here ya go.

On Mon, May 7, 2012 at 10:27 AM, chris dollin <ehog....@googlemail.com> wrote:
> On Mon, May 7, 2012 at 9:55 AM, Tom Vogel <voge...@gmail.com> wrote:
>>
>> In this contrived example:
>>
>> http://play.golang.org/p/uVOq8hq5Jn
>>
>> in Storage's implementation of Find it returns the result of calling a
>> function that returns a pointer to a type that satisfies the User
>> interface.  But when you compare the result with nil, it says it is
>> not nil (even though the underlying pointer is nil).

Because you're comparing an interface value to nil, you're seeing
if the interface is nil, not whether a pointer it happens to contain
is nil. (After all, the interface might not have a pointer value in it
at all.)

Consider two pointer types *A and *B that satisfy some interface I.
Suppose V is a variable of type I, and we write

   V = (*A)(nil)

The value stored inside V is nil, but V is not nil and you can recover
the type of the nil that it contains (with sufficient determination).


>> For AnotherFind, it checks the result of calling the function and
>> returns nil if the result is nil, and this works.

AnotherFind calls lookupId, which returns a pointer, and compares
that pointer -- not an interface -- to nil.


>> My question is:  what is the best way to compare an interface to nil?

   someInterface == nil


>> I'd prefer to write my code like the Find function and not like the
>> AnotherFind function.  But I'd like to be able to compare the result
>> with nil...

You're working with interfaces: you shouldn't be worrying about
what the type is of values inside the interface (unless you /need/ to).

Rob 'Commander' Pike

unread,
May 7, 2012, 1:32:36 PM5/7/12
to Kyle Lemons, chris dollin, golang-nuts

Kyle Lemons

unread,
May 7, 2012, 1:34:12 PM5/7/12
to Tom Vogel, golan...@googlegroups.com
The problem is in the implicit assignment of the nil return value into the interface.  Write it out:

u := lookup(id)
if u == nil {
   return nil
}
return u

That will prevent assigning a nil user into an interface.

Jake Brukhman

unread,
Nov 1, 2012, 12:16:46 AM11/1/12
to golan...@googlegroups.com
This discussion seems to imply that I cannot write the following method without reflection. Is this correct? The goal is to test an abitrary object for nil.

func AssertNotNil(o interface{}) {
if o == nil {
println("nil")
}
}

var x *int = nil
AssertNotNil(x) // doesn't work

Any way to implement this?

minux

unread,
Nov 1, 2012, 3:39:42 AM11/1/12
to Jake Brukhman, golan...@googlegroups.com
By using reflect.

for example:

Jesse McNelis

unread,
Nov 1, 2012, 4:01:38 AM11/1/12
to Jake Brukhman, golang-nuts
On Thu, Nov 1, 2012 at 3:16 PM, Jake Brukhman <jbr...@gmail.com> wrote:
This discussion seems to imply that I cannot write the following method without reflection. Is this correct? The goal is to test an abitrary object for nil.
Any way to implement this?

It doesn't make sense without reflection, since you don't know what the concrete type is you can't know if 'nil' is a reasonable value for it.  If you know what the type is then a type switch is a reasonable solution.


--
=====================
http://jessta.id.au


jac...@moonman.biz

unread,
Mar 12, 2014, 11:01:29 AM3/12/14
to golan...@googlegroups.com, Kyle Lemons
Mr. Vogel:

Like yourself, I have adopted the convention of (nil,nil) meaning 'not found'. This was my solution.

I added a function to the interface called 'Exists'. The implementation appears as follows:

func (usr *User) Exists() bool {
return usr != nil
}

I wouldn't exactly call it clever, but it works.

Considering how aged this post is, I am wondering what you finally went with?

Thanks.
Reply all
Reply to author
Forward
0 new messages