How to know if interface{} data is nil w/o reflecting?

37,097 views
Skip to first unread message

Jonathan Gold

unread,
Jun 4, 2012, 6:50:00 PM6/4/12
to golan...@googlegroups.com
I'm a bit stumped and wondering if I'm overlooking some way, besides reflection,
to determine whether the data pointed at by an interface{} is actually a nil
pointer:

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

Any ideas what I'm overlooking?

jonathan

Kevin Ballard

unread,
Jun 4, 2012, 7:01:30 PM6/4/12
to Jonathan Gold, golan...@googlegroups.com
If you know the type in question then you just use a type assertion, e.g. v2.(*someType) == nil.


If you don't know the underlying type of the interface then reflect is probably the right tool.

-Kevin

Kyle Lemons

unread,
Jun 4, 2012, 7:04:56 PM6/4/12
to Jonathan Gold, golan...@googlegroups.com
Nope.

This is a common source of confusion.  The basic answer is to never store something in an interface if you don't expect the methods to be called on it.  The language may allow it, but that violates the semantics of the interface.  To expound, a nil value should usually not be stored in an interface unless it is of a type that has explicitly handled that case in its pointer-valued methods and has no value-receiver methods.

Jesse McNelis

unread,
Jun 4, 2012, 7:54:17 PM6/4/12
to Jonathan Gold, golan...@googlegroups.com
On Tue, Jun 5, 2012 at 8:50 AM, Jonathan Gold <jgol...@gmail.com> wrote:
> I'm a bit stumped and wondering if I'm overlooking some way, besides reflection,
> to determine whether the data pointed at by an interface{} is actually a nil
> pointer:

You just use a type assertion. If you don't know the type, then you
don't know if nil is a valid value for it and thus have no business
checking for it.


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

tmp...@hotmail.com

unread,
Oct 30, 2017, 1:30:06 PM10/30/17
to golang-nuts
I found this a little bit non sequitur - if I want to call interface function I have a perfect business to check if underlying object is not nil before call just to avoid panic on call. Besides underlying nil in interface may be used to signal condition for variety of types implementing this interface, and since there is no inheritance in Go - sometimes it's the only proper way to indicate such condition.

Jesse McNelis

unread,
Oct 30, 2017, 7:01:02 PM10/30/17
to tmp...@hotmail.com, golang-nuts
On Tue, Oct 31, 2017 at 2:25 AM, <tmp...@hotmail.com> wrote:
> I found this a little bit non sequitur - if I want to call interface
> function I have a perfect business to check if underlying object is not nil
> before call just to avoid panic on call. Besides underlying nil in interface
> may be used to signal condition for variety of types implementing this
> interface, and since there is no inheritance in Go - sometimes it's the only
> proper way to indicate such condition.

In Go you can call a method on nil without a panic, this means that
unless you know the type you don't know if a nil value of that type is
a valid value to call a method on or not. You would be making a big
assumption about the type contained within the interface{} if you
checked that value for nil.

Of course since you don't know the type of the value inside the
interface{} it might not even be a value comparable to nil, in which
case should the comparison return false or panic?

oju...@gmail.com

unread,
Oct 31, 2017, 10:25:46 AM10/31/17
to golang-nuts
Not being able to test for a nil interface is a Go language bug.

Humans are fallible, so are our projects. Every project has its share of errors.
Go, despite being a great tool we all love, is no exception to that universal rule.


Ayan George

unread,
Oct 31, 2017, 10:34:44 AM10/31/17
to golan...@googlegroups.com


On 10/31/2017 10:25 AM, oju...@gmail.com wrote:
> Not being able to test for a nil interface is a Go language bug.
>

Just curious: How would you do this without type assertion or reflection?

Ian Lance Taylor

unread,
Oct 31, 2017, 10:44:18 AM10/31/17
to JuciÊ Andrade, golang-nuts
Agreed about fallibility and errors, but Go is a programming language
so it's necessary to be precise. Go makes it straightforward to test
for a nil interface value: write `v == nil`. What you are talking
about is something different: testing whether an interface holds a
value of some type, where the value of that type happens to be nil.
Go makes a clear and necessary distinction between an interface that
is nil and an interface that holds a value of some type where that
value is nil. It would be a mistake to remove that distinction, and
once you accept that it's hard to see what we can do. See also
https://golang.org/doc/faq#nil_error .

Ian

oju...@gmail.com

unread,
Oct 31, 2017, 12:33:54 PM10/31/17
to golang-nuts
Ian, with all due respect, I beg to differ.

Let's look at that example posted 5 years back:

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

Yes, that is the proper behavior according to the rules, we have a FAQ entry, fine, but ... put simply: that makes no sense. Why? Because we, the users, expect the code to work the other way. That is a big surprise and we don't need the tool creating surprises for us, much to the contrary.

The internal layout Go uses to store an interface should not mess with the expected behavior. If interface is two separate fields, or just a pointer, or refers to a bitmap stored on the Moon, I don't care. I shouldn't care. The fact that today we must tell every new Go user this whole story is a shame. Go is meant to be easy, after all.

The behavior of a software of mine is not what my user expect? In my book that means I have a bug. Even with a very reasonable explanation, that remains a bug. I can spend hours explaining a strange behavior to my user. He will tell me: "Oh, yes. Now I got it, thanks. Fix that".

That reminds me of an old adage:

“If the map doesn't agree with the ground the map is wrong”


I sincerely hope Go 2 will have it fixed.

oju...@gmail.com

unread,
Oct 31, 2017, 12:43:00 PM10/31/17
to golang-nuts
Today you can't, Ayan.

Bruno Albuquerque

unread,
Oct 31, 2017, 12:43:37 PM10/31/17
to oju...@gmail.com, golang-nuts
I am not sure what exactly is the issue you are complaining about. You can think of interface as a container for some data type. The container can be nil and the data contained in it can be nil. This looks reasonable to me as much as having a C++ vector that contains nil (well, nullptr) pointers.



--
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...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Marvin Renich

unread,
Oct 31, 2017, 12:47:18 PM10/31/17
to golang-nuts
* oju...@gmail.com <oju...@gmail.com> [171031 12:34]:
> Ian, with all due respect, I beg to differ.
>
> Let's look at that example posted 5 years back:
>
> http://play.golang.org/p/Isoo0CcAvr
>
> Yes, that is the proper behavior according to the rules, we have a FAQ
> entry, fine, but ... put simply: that makes no sense. Why? Because we, the
> users, expect the code to work the other way. That is a big surprise and we
> don't need the tool creating surprises for us, much to the contrary.

I beg to differ. I, a user, very much expect the current behavior and
would be very surprised if it worked the way you are suggesting.

Ian's msg gives good reasons why it would be wrong to change the
behavior, even if we could go back in time to before the release of Go
1 and the Compatibility Guarantee.

...Marvin

Axel Wagner

unread,
Oct 31, 2017, 1:10:25 PM10/31/17
to oju...@gmail.com, golang-nuts
On Tue, Oct 31, 2017 at 5:33 PM, <oju...@gmail.com> wrote:
The internal layout Go uses to store an interface should not mess with the expected behavior. 
If interface is two separate fields, or just a pointer, or refers to a bitmap stored on the Moon, I don't care. I shouldn't care.
  
And you don't have to care. This is not an implementation detail, it is a spec-detail. It is a consequence of

a) Methods can be declared on any type, including pointers
b) Methods can be called on any value of that type, including its zero value
c) An interface is a type for "any type with the following sets of methods"

Whether you represent an interface as one word, two words, zero words or one billion words is irrelevant, as long as you implement Go, you have to adhere to these rules and they imply the criticized behavior. Personally, I have a gripe with the fact that the FAQ justifies this behavior with an implementation detail, when really it's a consequence of the language. The rules a), b) and c) make individually total sense. It makes sense to be able to declare methods on pointers, as it is expected that methods can modify state from other imperative languages. It makes sense that methods can be called on zero values, because they should be a property of the type, not the value. It makes sense to have the notion of a method set as an interface.

I sincerely hope Go 2 will have it fixed.

https://github.com/golang/go/issues/21538 has already been filed and there might be other issues amounting to the same thing. I think it is fair to say, that a) for Go1, this can't be changed either way and b) for Go2, the community is aware of the confusion.

Jesse McNelis

unread,
Oct 31, 2017, 7:17:41 PM10/31/17
to JuciÊ Andrade, golang-nuts
On Wed, Nov 1, 2017 at 3:42 AM, <oju...@gmail.com> wrote:
> Today you can't, Ayan.
>

It's very consistent, you can't compare an interface value reliably to
any untyped constant.
Because there is no way for the compiler to figure out what type it should take.

https://play.golang.org/p/4Fn0YNE2md

Ayan George

unread,
Nov 1, 2017, 5:06:31 AM11/1/17
to golan...@googlegroups.com


On 10/31/2017 12:42 PM, oju...@gmail.com wrote:
> Today you can't, Ayan.
>

Right -- I understand that. I'm asking how would you propose Go do
that? What changes would you make to fix this?

I'm asking: If you claim Go is fundamentally broken in this way, how
would you fix it?

-ayan


oju...@gmail.com

unread,
Nov 1, 2017, 7:19:19 AM11/1/17
to golang-nuts
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."

Ayan George

unread,
Nov 1, 2017, 9:37:54 AM11/1/17
to golan...@googlegroups.com


On 11/01/2017 07: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.
>

I think I understand what you're saying. The thing is: You changed the
type of r and I don't believe anyone ever promised that you can change
the type of a variable to an interface AND preserve its behavior.

Would you expect r to behave the same if you changed it from type string
to an int?

Also, you understand how interfaces work. I think our hypothetical
developer should simply understand how interfaces work as well; it is
reasonable to expect developers to know the language.

I don't think it is reasonable to introduce this kind of ambiguity to
protect developers from actually learning the language. I think
interfaces as they are are clear and consistent and making nil
interfaces suddenly equal to interfacess with nil values is more
'subtle' and harder to understand.

Ain

unread,
Nov 1, 2017, 10:23:47 AM11/1/17
to golang-nuts

Point is, in that case compiler would catch it for you and you wouldn't be able to compile until you fix all the parts of the code which now doesn't make sense. Not so in the case JuciÊ Andrade pointed out.


ain

Ian Lance Taylor

unread,
Nov 1, 2017, 10:32:21 AM11/1/17
to JuciÊ Andrade, golang-nuts
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

Jack Christensen

unread,
Nov 1, 2017, 1:09:33 PM11/1/17
to golan...@googlegroups.com
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

Axel Wagner

unread,
Nov 1, 2017, 1:21:48 PM11/1/17
to Jack Christensen, golang-nuts
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).

--
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+unsubscribe@googlegroups.com.

Bryan Mills

unread,
Nov 2, 2017, 12:46:38 AM11/2/17
to golang-nuts
C++ had a similar change with the `nullptr` literal in C++11: `NULL` was overloaded between pointers and integers, whereas `nullptr` can only be (implicitly converted to) a pointer.

Volker Dobler

unread,
Nov 2, 2017, 3:55:09 AM11/2/17
to golang-nuts
On Wednesday, 1 November 2017 12:19:19 UTC+1, JuciÊ Andrade 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.

This is a nice argument. But please consider a small variation on it:
Let's start of with as you did: r is a pointer and you check its nilness:

    r *myType

    if r != nil {
        r.doSomething()
    }
"Then, years later, other programmer in my team decides to [...]
[add one more level of indirection] to better capture a new
understanding of the problem at hand, changing the type of r to:"

    r **myType


"Subtly, the meaning of" 

    if r != nil {
        r.doSomething()
    }

"changes. Under the right circumstances our software starts to
behave strangely. What?"

Of course it will! And this is (I hope undoubtedly) not a language
design error. Of course it would sometimes be handy to be able
to write
    var a ***int
    if a _!=_ nil { ... }
with an operator _!=_ with semantics like
    if a != nil && *a != nil && **a!=nil { ... }
(all the way down).
But there currently is no such deep-down-comparison operator
(and it presumably would be hard to design a consistent one).

What you have been asking for is some magic to unpeel the topmost
interface level. But where to stop? How should
    var b *myInterface
    if b != nil { ... }
behave? Check if b actually is non-nil, then check if the interface
itself is non-nil and then peek inside the interface and check if there
is a non-nil value?

Just because a single example demonstrates that some behaviour
would be helpful and help mitigate an error does not mean it does
not open a different can of worms.

V.



oju...@gmail.com

unread,
Nov 3, 2017, 5:24:30 AM11/3/17
to golang-nuts
Could somebody please point me to any example of comparing an interface to nil, in production code? Thanks.

Ayan George

unread,
Nov 3, 2017, 5:31:47 AM11/3/17
to golan...@googlegroups.com


On 11/03/2017 05:23 AM, oju...@gmail.com wrote:
> Could somebody please point me to any example of comparing an
> interface to nil, in production code? Thanks.
>

Does checking if a variable of type error is nil count?

-ayan

oju...@gmail.com

unread,
Nov 3, 2017, 6:10:19 AM11/3/17
to golang-nuts
Yes, Ayan, you are quite correct. There are a lot of comparisons to check if an error is nil. It has it's own FAQ entry: https://golang.org/doc/faq#nil_error

Sincerely, what I am after is an example of a situation where the solution proposed by Dave Cheney would create a problem, like "See here. In this situation the proposed change would break my code."

When comparing error to nil, Dave's change would work just fine. That FAQ entry would not be needed anymore.

Jakob Borg

unread,
Nov 3, 2017, 6:30:09 AM11/3/17
to oju...@gmail.com, golang-nuts
I often do nil checks on interfaces in places like constructors that may or may not have received optional parameters. In some cases as a parameter that may be nil if no implementation is required, in some cases where a functional option setting the interface was not given. Typically this looks something like:

func Walk(ctx context.Context, cfg Config) (chan protocol.FileInfo, error) {
w := walker{cfg}

if w.CurrentFiler == nil {
w.CurrentFiler = defaultCurrentFiler{}
}
        …
}

where the field is set to some default implementation when nil. It’s also not uncommon to have nil implementations of that interface, especially in tests:

type mockCurrentFiler struct{}

func (*mockCurrentFiler) CurrentFile(string) whatever {
    return nil
}

var testCurrentFiler *mockCurrentFiler // nil


cfg.CurrentFiler = testCurrentFiler // == nil in the new regime
Walk(ctx, cfg)

This would break, in a surprising way as the default implementation would be used instead of the given mock implementation. Clearly the test can be refactored:

cfg.CurrentFiler = &mockCurrentFiler{} // not nil

but yes, the change would break code.

I’m not saying that having this change in Go 2 would necessarily be a bad idea, but the current Go 1 behavior makes sense in Go 1 and there is definitely code that depends on it.

//jb

--
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...@googlegroups.com.

oju...@gmail.com

unread,
Nov 3, 2017, 12:30:13 PM11/3/17
to golang-nuts
This thread helped me to understand better the current scenario and the implications of a future change.

I would be glad to recognize if this conversation had changed my mind, but it didn't.

Some programmers discovered that they could use this "valid nil interface" to do some smart tricks, as Jakob kindly has shown. While I do recognize that was indeed smart, Jakob offered another easy way of attaining the desired effect for his constructor. It would be pretty easy if he had to code that way to begin with.

I consider unfortunate the fact that I can't safely use an interface where previously I used a pointer. To me, at least, that is a natural evolutionary path for a piece of software as soon as the developer discover opportunities to leverage the commonality of an interface. I think such possibility would be more broadly useful than what we can do now.

Go has a bunch of interesting tricks and useful idioms, but this trick is proving costly.

Thanks to everyone.

Matt Harden

unread,
Dec 30, 2017, 12:07:31 AM12/30/17
to oju...@gmail.com, golang-nuts
I really wish Go had not chosen to propagate Hoare's billion-dollar mistake. I do realize it's all tied up with the idea that initialization is cheap and zero values should be useful when possible, and therefore pointers, interfaces, channels, etc. need zero values.

I wonder how different Go would have been if we had required all pointers and interfaces (only) to be initialized, and made the zero value for maps a writable empty map. In cases where nil pointers and interfaces are useful, it seems to me that sentinel values would serve the purpose equally well. For example, comparing errors with (ok) would be (one character) shorter, more meaningful and less confusing than comparing with nil, which can be so confusing for newcomers that we have an FAQ for it. Few would be surprised to find (e != ok) when (e == (*myerror)(nil)) -- and if there were no nil pointers, it wouldn't even be a valid question to ask. We could still use pointers as stand-ins for Optional types, just with sentinel values like sql.NullInt64 to serve the purpose nil does.

I know this is likely a non-starter for Go2, for good reasons - virtually all Go code would need significant, probably manual refactoring, and interoperability with other languages would suffer, to name two that come to mind.

I think what I really want is Haskell plus all the benefits Go has relative to it, including Go's incredibly simple language spec, standard library, short compile times, etc. Is that too much to ask? :-)

--

matthe...@gmail.com

unread,
Dec 30, 2017, 11:08:53 AM12/30/17
to golang-nuts
Storing a pointer in a reference type seems absurd to me.

Matt

Matt Harden

unread,
Dec 30, 2017, 2:22:37 PM12/30/17
to matthe...@gmail.com, golang-nuts
I don't know what you mean by "reference type" - as I understand it, that's not a meaningful phrase in Go. Did you mean "interface"? If so, we store pointers in interfaces all the time in Go. When we set an interface variable i to x, we are semantically making a copy of x and storing it in i. We won't be able to modify x using i (because it has a copy of x, not a pointer to the original). If x is a pointer to something, then we will be able to modify that something using i.

matthe...@gmail.com

unread,
Jan 1, 2018, 11:53:32 AM1/1/18
to golang-nuts
Since an interface can be nil I’ve been assuming interface behaves like slice with a pointer to the concrete data within a reference struct (that also includes the data type) which is passed around as an interface var.

This playground shows that the interface var is a similar reference type to slice: https://play.golang.org/p/PIWpyrpwNq5

I didn’t know where to look in the Go source to find the definition of an interface (src/runtime/type.go, src/runtime/iface.go, src/go/types/type.go, and src/cmd/compile/internal/types/type.go weren't immediately clear to me). The specification says an interface stores a value; my misunderstanding is that while the interface var may refer to data elsewhere, this data is a copy of the original.

So using a pointer assigned to an interface as a way to save stack space is absurd, but using a pointer assigned to an interface as a way to modify the original data does make sense. Arguing about nil interface vs nil pointer in an interface is not absurd, I apologize for my statement.

Matt

David Collier-Brown

unread,
Jan 1, 2018, 7:40:07 PM1/1/18
to golang-nuts
Drifting back toward the original subject, I'm reminded of the non-bsd-c idiom of

char *foo(char *p) {
    if (p != NULL && *p != NULL) {
        return some string operation...
    }
...

It seems logical to check the type of the contents of an interface
type, and its presence in a function that can take nil types and
nil contents, much as in the C idiom. 

Mind you, I do find type assertions a bit clunky. 

--dave

Axel Wagner

unread,
Jan 2, 2018, 2:40:08 AM1/2/18
to David Collier-Brown, golang-nuts
I don't understand this comparison. The C idiom you mention is concretely typed (i.e. C doesn't have interfaces, so it doesn't have dynamic types), so I fail to see what it has to do with interfaces. And it makes *far* more sense to check if you got passed a nil-pointer, than to check the concrete value of an interface -- i.e. something like this makes of course some sense, in Go:

func Foo(p *string) {
    if p != nil {
        *p = doSomeStuff()
    }
}

It makes sense to check p for nil, because you know its type and you know you can't use it, if its nil. It's thus a very different problem than what this thread is about.

Moreover, how does, what you say what was said above? i.e. a) As a user of an interface, its dynamic value shouldn't concern you, in general, b) not all zero values are nil, so checking for nil to see whether the dynamic value is the zero value doesn't make sense and c) the zero value - including nil - is a perfectly valid implementation of an interface?



--
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+unsubscribe@googlegroups.com.

David Collier-Brown

unread,
Jan 2, 2018, 8:10:12 AM1/2/18
to golan...@googlegroups.com
I was responding to the case where one is passed an interface, expects
it to contain a typed value, and
it does not.

--dave

scud...@gmail.com

unread,
May 8, 2018, 9:49:23 AM5/8/18
to golang-nuts
In my case, being a new go learner the following bit of code stumped me. I am receiving a interface{} value and I am trying to figure out the best way to print it. If the value supports the fmt.Stringer() interface then I want to use that, otherwise i can do some other things. So I came up with this:

func printer(foo interface{}) string {

     switch t := foo.(type) {
     ....
     case fmt.Stringer:
             return t.String()
      ...
}

But this crashes when foo is really a nil pointer to a type which does support Stringer. The problem is that there is no way for me to actually know foo is nil and avoid it. I can not compare foo to nil because foo is an interface so foo==nil is false, and my type assertion is converting it to an interface too so i can not compare that to nil either. Literally the only way this code can work is to just catch the error and return the string "nil". This is hugely confusing behavior especially for a new comer.

Apart for this it seems to me the natural way to implement this kind of code - for example in python the code is natural, and I wanted to carry the same general technique to go:

def printer(foo):
   if isinstance(foo, Stringer):
     return foo.String()
  ...

Thanks
Michael.



On Tuesday, June 5, 2012 at 8:50:00 AM UTC+10, jgoldbg wrote:
I'm a bit stumped and wondering if I'm overlooking some way, besides reflection,
to determine whether the data pointed at by an interface{} is actually a nil
pointer:

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

Any ideas what I'm overlooking?

jonathan

Jakob Borg

unread,
May 8, 2018, 10:06:34 AM5/8/18
to scud...@gmail.com, golang-nuts
On 8 May 2018, at 15:26, scud...@gmail.com wrote:
But this crashes when foo is really a nil pointer to a type which does support Stringer.

The crash isn’t on “your” side though, it’s presumably inside the String() method. Hence, the caller passed you something invalid that you can’t handle. I’d argue that avoiding this is their responsibility.

My case is made weaker by how fmt.Println and friends handle this though. They’ll call the String() method, recover from the panic, use reflect to see if the boxed value is nil, and print a “<nil>”. I guess this is friendly, but not something I think normal code should do.

(In your specific case you seem to be reimplementing fmt.Sprint; you can just use that instead. :)

//jb

Michael Cohen

unread,
May 8, 2018, 10:20:18 AM5/8/18