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

26046 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
to Jakob Borg, golang-nuts
Well no - the error I get is that I am attempting to call String() method on a null receiver - so the caller just passed me a regular nil object. The issue is that I am trying to make a generic polymorphic function which should be able to handle whatever is thrown at it - so I guess reflect is necessary.

 I think I am supposed to detect the null receiver before calling String() on it. I ended up using this little utility:


func isNil(a interface{}) bool {
  defer func() { recover() }()
  return a == nil || reflect.ValueOf(a).IsNil()
}

But this feels really hacky when I really just want to say if value != nil { ....} .

Thanks
Michael.

Jakob Borg

unread,
May 8, 2018, 10:54:54 AM5/8/18
to mi...@velocidex.com, golang-nuts


> On 8 May 2018, at 16:19, Michael Cohen <scud...@gmail.com> wrote:
>
> Well no - the error I get is that I am attempting to call String() method on a null receiver - so the caller just passed me a regular nil object.

They passed you a totally legit fmt.Stringer which then panicked when you called String() on it. That’s their fault.

> I think I am supposed to detect the null receiver before calling String() on it. I ended up using this little utility:

I really don’t think you are. But it’s your code. :)

//jb

Ian Lance Taylor

unread,
May 8, 2018, 10:55:56 AM5/8/18
to mi...@velocidex.com, Jakob Borg, golang-nuts
On Tue, May 8, 2018 at 7:19 AM, Michael Cohen <scud...@gmail.com> wrote:
>
> Well no - the error I get is that I am attempting to call String() method on
> a null receiver - so the caller just passed me a regular nil object. The
> issue is that I am trying to make a generic polymorphic function which
> should be able to handle whatever is thrown at it - so I guess reflect is
> necessary.
>
> I think I am supposed to detect the null receiver before calling String()
> on it. I ended up using this little utility:
>
> https://stackoverflow.com/questions/13476349/check-for-nil-and-nil-interface-in-go
>
> func isNil(a interface{}) bool {
> defer func() { recover() }()
> return a == nil || reflect.ValueOf(a).IsNil()
> }
>
>
> But this feels really hacky when I really just want to say if value != nil {
> ....} .

I think there may be some confusion here. Go doesn't have a "regular
nil object." Specific types can be `nil`. In particular, pointer
types can be `nil`.

When a type implements a `String` method it is possible to call that
method with a `nil` pointer. In general it is possible to call any
method with a `nil` pointer. That is not an error.

Some specific implementations of a `String` method may panic when
called with a `nil` pointer. For better or for worse, the fmt package
has special handling for this.

What this means is that unless you have some special knowledge of the
type you are working with, you should not check for `nil` before
calling the `String` method. For some types the `String` method will
correctly handle `nil`. If you have types with a `String` method that
does not correctly handle `nil`, then it's worth pondering why and how
you got a `nil` pointer for this type in the first place. But if you
can reasonably have a `nil` pointer, and can reasonably expect that
the `String` method will panic in that case, then what you should do
is call `fmt.Sprint(v)`. That will do the right thing whether v's
`String` method handles `nil` or not.

Ian

Michael Cohen

unread,
May 8, 2018, 9:18:42 PM5/8/18
to Ian Lance Taylor, mi...@velocidex.com, Jakob Borg, golang-nuts
Thanks Ian for the thorough explanation - again I apologize for asking noob questions :-).

The issue in this case was this error:

panic: value method github.com/shirou/gopsutil/process.Process.String called using nil *Process pointer

which seems to be coming from the go runtime itself. Certainly the String method of Process does not have a pointer receiver:

func (p Process) String() string {
        s, _ := json.Marshal(p)
        return string(s)
}

So it makes sense for the runtime to panic when we attempt to call it on a nil pointer. I looked at the code for the fmt.Sprintf method as you suggested and it seems to be doing the same thing as what my code is doing - i.e. it catches the panic and then calls reflect to check if it is because its a nil pointer. So i guess what feels hacky is really the way it is supposed to be done in golang. 

I wrote the following code to try to understand the behavior more https://play.golang.org/p/kKWGCeacAEM
package main

import (
"fmt"
)

func type_function(a *int) {
fmt.Println("type_function: ", a == nil)
 }

func interface_function(a interface{}) {
fmt.Println("interface_function: ", a == nil)
}

func main() {
type_function(nil)           // true
interface_function(nil)   // true

var foo *int = nil
fmt.Println("is foo nil: ", foo == nil)
interface_function(foo)  // false ... ?
}

It seems to me that if a function accepts a pointer type - it is ok to compare a pointer type against nil. But if a function accepts an interface as an arg it is never safe to compare an interface against nil because from inside the function you have no idea if the caller called with actual nil, or a variable who's value is nil (this difference is very weird because this is not how most languages behave - a variable is usually a full substitute to the literal value it holds).

It seems to me that the compiler should at least warn when someone is comparing an interface to nil (or maybe the linter should warn). It does not seem that this could ever be what you actually want and it is always a subtle bug just waiting to bite.

Thanks
Michael.

Ian Lance Taylor

unread,
May 9, 2018, 12:09:59 AM5/9/18
to Michael Cohen, Jakob Borg, golang-nuts
On Tue, May 8, 2018 at 6:17 PM, Michael Cohen <scud...@gmail.com> wrote:
>
> It seems to me that the compiler should at least warn when someone is
> comparing an interface to nil (or maybe the linter should warn). It does not
> seem that this could ever be what you actually want and it is always a
> subtle bug just waiting to bite.

It's perfectly reasonable to compare an interface to nil if you want
to see whether it has been set to anything. In particular it's very
common in Go to write `err != nil`, so clearly warning about every
comparison of an interface value to `nil` is a non-started. See
https://golang.org/doc/faq#nil_error. But see also
https://golang.org/issue/22729.

The issue of passing a nil pointer to a value method is a good reason
to write your String methods as pointer methods.

Ian

Louki Sumirniy

unread,
May 9, 2018, 4:59:45 AM5/9/18
to golang-nuts
Can you not convert it to an unsafe.Pointer and check for that being nil?

cpu...@gmail.com

unread,
Apr 10, 2020, 1:17:51 PM4/10/20
to golang-nuts
Good morning!

I realize I'm reviving an age-old discussion here and apologize for bringing up the undead. I happend to run into this when my application panicked when some interfaces where initialized with nil mock objects instead of being left uninitialized as in production mode.

Axel said:

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.
 
This would be an example where a nil implementing fooer is never caught:

type fooer interface {
 foo
()
}

type other
struct{}

func
(o *other) foo() {} // implement fooer

func main
() {
 
var f fooer

 
var p *other // nil
 f
= p // it is a fooer so I can assign it

 
if f == nil {
   
// will not get here
 
}
}


My confusion comes from the point that the nil interface is apparently not "a nil-pointer with the correct method set" while *other is even if nil.

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.

The above is a case where that might happen. In can be worked around but it is unexpected unless the programmer is deeply rooted in the language definition.
 
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).

Seems as of today that there is no tooling to support that check. Maybe it's not a widespread issue. 

Axel Wagner

unread,
Apr 11, 2020, 9:20:53 AM4/11/20
to cpu...@gmail.com, golang-nuts
On Fri, Apr 10, 2020 at 7:17 PM <cpu...@gmail.com> wrote:
I realize I'm reviving an age-old discussion here and apologize for bringing up the undead. I happend to run into this when my application panicked when some interfaces where initialized with nil mock objects instead of being left uninitialized as in production mode.

Let's imagine a world in which `foo == nil` also is true if `foo` is an interface-value containing a nil-pointer. Let's say in this world, someone sends a message to golang-nuts. They wrote a mock for the same code. And since it's just a mock, they just returned static value from its methods and didn't need to care if the pointer was nil or not. They are confused, because the passed in this mock, but the code just assumed the field was uninitialized and never called into their mock. What would you tell them? Why is their confusion less valid?

This would be an example where a nil implementing fooer is never caught:

type fooer interface {
 foo
()
}

type other
struct{}

func
(o *other) foo() {} // implement fooer

func main
() {
 
var f fooer

 
var p *other // nil
 f
= p // it is a fooer so I can assign it

 
if f == nil {
   
// will not get here
 
}
}


My confusion comes from the point that the nil interface is apparently not "a nil-pointer with the correct method set" while *other is even if nil.

In the code you posted, even a nil *other is a perfectly fine implementation of fooer. You can call `(*other)(nil).foo()` without any problems.
So, as you illustrated, calling methods on a nil-pointer can be totally fine. A nil-interface, OTOH, doesn't have any methods to call, as it doesn't contain a dynamic value. If you write `(*other)(nil).foo()`, it is completely clear what code gets called - even if that code *might* panic. If you write `fooer(nil).foo()`, what code should be called in your opinion?

I think it's easy to see that a nil-interface and a nil-pointer stored in an interface are very different things. Even from first principles, without deep knowledge of the language. And if they are obviously different, I don't understand why you'd find it confusing that they are not the same in this particular manner.

The above is a case where that might happen. In can be worked around but it is unexpected unless the programmer is deeply rooted in the language definition.

I fully agree with that. What I *don't* agree with, is where you attribute the problem here. You say, the problem is that the nil-check is ill-behaved. I say that - if anything - the original nil-assignment is ill-behaved. Having `(fooer)((*other)(nil)) == nil` be true is semantically wrong, because by checking against `nil`, you are checking if you have a correct implementation - and you might well have a correct implementation, even if it's using a nil-pointer.

Note, that the contained pointer being nil isn't the *only* case in which calling the method might panic. For example, what about this code?
Shouldn't the `nil`-check also catch that? After all, calling the method panics, so it's clearly not a valid implementation - even if x itself is not nil. Why is a nil-pointer more special than any other value that causes a method to panic? 

Seems as of today that there is no tooling to support that check. Maybe it's not a widespread issue.

As of today, the language also isn't changed :) Maybe someone who think this is important enough to change the language, could also feel it's important enough to write this tooling.


--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/e0dbcd38-510e-43b9-b363-2af1c636250b%40googlegroups.com.

Robert Engels

unread,
Apr 11, 2020, 9:48:28 AM4/11/20
to Axel Wagner, cpu...@gmail.com, golang-nuts
I agree with the OP. The usefulness of nil interfaces is pretty limited. Show me a useful case that cant easily be implemented with non-nil interfaces. 

I would argue that allowing nil interfaces causes more subtle latent bugs and makes it harder to reason about the correctness of code when reviewing it. 

It just feels wrong. I realize I’m probably in the minority here but the OP is not alone. 

Aviv Eyal

unread,
Aug 23, 2020, 3:58:51 PM8/23/20
to golang-nuts
I was trying to show that the current behavior is confusing and that fmt.Print() needing to resort to panic-and-recover is kinda code smell, but I sorts-of convinced myself that the current behavior is right, or at least consistent.

In my code, I got bit because I sometimes use v *Type to denote "I may or may not have a value here" (where Type is a value-type). 
This is probably a bad practice on my behalf, because I break the Liskov substitution principle: there is a value of `*Type` that is not a valid value of `Type`, and I let this value slip by.

In this case, `v Type` implements Stringer (i.e. valid callee for `v.String()`, but `v *Type`, in the strictest sense, does not.
The only reason we can write:

    func (Type) String() string {...}
    v *Type = &Type{...}
    _ = v.String()

and have it compile, is syntactic sugar: `v` gets implicitly de-referenced, and there's an implicit assumption that it's not nil.
And there's a matching syntactic sugar for converting `Type` to a `*Type`.

So, In the code:

    func (Type) String() string {...}

    v *Type = nil
    r interface{} = v
    _, ok = r.(Stringer)

What I really want to ask is "Can I, at runtime, call r.String()?", whereas the question Go answers is "Is any of `r`, `*r`, or `&r` defines .String()?" - which matches the static semantics of `r.String()`.

So, while I should probably not use *Type as a replacement for Optional<Type>, I think it might make sense to have some operator that can determine, at run-time, if a call `r.String()` is valid (including a nil-check).


-- Aviv

Denis Cheremisov

unread,
Aug 23, 2020, 4:15:27 PM8/23/20
to golang-nuts
You may use something like this

        value2 := *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer(&value)) + 8))
        if value2 == 0 {
                return true
        }

on AMD64, should work also for any 64 bit architecture (at least I believe so). Remember though this is hacky and may stop working once.


воскресенье, 23 августа 2020 г. в 22:58:51 UTC+3, Aviv Eyal:

Ian Lance Taylor

unread,
Aug 23, 2020, 11:52:30 PM8/23/20
to Denis Cheremisov, golang-nuts
On Sun, Aug 23, 2020 at 1:16 PM Denis Cheremisov
<denis.ch...@gmail.com> wrote:
>
> You may use something like this
>
> value2 := *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer(&value)) + 8))
> if value2 == 0 {
> return true
> }
>
> on AMD64, should work also for any 64 bit architecture (at least I believe so). Remember though this is hacky and may stop working once.

You could do that, but please don't.

Ian
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/c1ed2e38-6215-4ed2-8357-f8b5d83bf1a7n%40googlegroups.com.

alex.be...@gmail.com

unread,
Aug 24, 2020, 12:08:17 AM8/24/20
to golang-nuts
Can we at least move with the https://github.com/golang/go/issues/22729 , please? Anything will help with the current mess.
> To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

targe...@gmail.com

unread,
Aug 27, 2020, 4:06:00 AM8/27/20
to golang-nuts
Not sure if it was mentioned here, but IMO the main issues isn't nil data itself, but how easy it's created. It'd be much less of a surprise if creating nil-data required explicit cast from nil struct pointer to interface pointer and resulted in just nil interface pointer in case of implicit cast. Though such change is almost certainly breaking one.

Axel Wagner

unread,
Aug 27, 2020, 4:49:16 AM8/27/20
to targe...@gmail.com, golang-nuts
On Thu, Aug 27, 2020 at 10:06 AM targe...@gmail.com <targe...@gmail.com> wrote:
Not sure if it was mentioned here, but IMO the main issues isn't nil data itself, but how easy it's created. It'd be much less of a surprise if creating nil-data required explicit cast from nil struct pointer to interface pointer and resulted in just nil interface pointer in case of implicit cast. Though such change is almost certainly breaking one.

This would require to insert extra nil-checks when assigning a pointer-value to an interface, as the compiler can't know if a pointer is nil or not. Personally, I would also find it very confusing, if converting a T to a T changed program behavior (though arguably, there is one such case currently with `uintptr(uintptr(unsafe.Pointer))`. But usage of `unsafe` seems sufficiently advanced).
 

targe...@gmail.com

unread,
Aug 27, 2020, 5:09:31 AM8/27/20
to golang-nuts
> This would require to insert extra nil-checks when assigning a pointer-value to an interface, as the compiler can't know if a pointer is nil or not.
it would definitely. Though price for consistency looks very much acceptable.

> Personally, I would also find it very confusing, if converting a T to a T changed program behavior
Sorry, didn't get it. Are you saying that nil pointer -> nil interface is more confusing?

Axel Wagner

unread,
Aug 27, 2020, 5:20:59 AM8/27/20
to targe...@gmail.com, golang-nuts
On Thu, Aug 27, 2020 at 11:10 AM targe...@gmail.com <targe...@gmail.com> wrote:
it would definitely. Though price for consistency looks very much acceptable.

I don't think "consistency" is at all the right word here. If anything, things would get *less* consistent, not more.

> Personally, I would also find it very confusing, if converting a T to a T changed program behavior
Sorry, didn't get it. Are you saying that nil pointer -> nil interface is more confusing?

I'm saying the current situation is less confusing than what you describe, yes.

AIUI, with what you describe, if I have a variable `x` of type `*T` and an interface variable `y`, then `y = x` and `y = (*T)(x)` have different semantics. I think it is strange to have a conversion of `x` *to its own type* have any sort of semantic implication. It should be a no-op.

targe...@gmail.com

unread,
Aug 27, 2020, 5:39:11 AM8/27/20
to golang-nuts
> I'm saying the current situation is less confusing than what you describe, yes.
> AIUI, with what you describe, if I have a variable `x` of type `*T` and an interface variable `y`, then `y = x` and `y = (*T)(x)` have different semantics. I think it is strange to have a conversion of `x` *to its own type* have any sort of semantic implication. It should be a no-op.

It may be expressed in some different way. To me, if `x == nil` and then `y != nil` after `y = x` is much more confusing. If you ask my opinion, I would make interfaces compare to nil on just data pointer. If one wanted interface which doesn't require data, he could've easily created one with static stub variable. No additional checks, no "semi-nil" fat pointers, everything simple and consistent.

Axel Wagner

unread,
Aug 27, 2020, 6:14:17 AM8/27/20
to targe...@gmail.com, golang-nuts
On Thu, Aug 27, 2020 at 11:39 AM targe...@gmail.com <targe...@gmail.com> wrote:
> I'm saying the current situation is less confusing than what you describe, yes.
> AIUI, with what you describe, if I have a variable `x` of type `*T` and an interface variable `y`, then `y = x` and `y = (*T)(x)` have different semantics. I think it is strange to have a conversion of `x` *to its own type* have any sort of semantic implication. It should be a no-op.

It may be expressed in some different way. To me, if `x == nil` and then `y != nil` after `y = x` is much more confusing.

And obviously you are not alone. Even though I really don't understand why this isn't just one of those "you learn about it, you know about it, you never run into any problems again" type of things. It does seem to come up sufficiently often to be a problem. And there are solutions that I think are fine. For example, using a different identifier (say `none`) to denote the zero-value of interfaces would be fine by me.

But solutions that try to give special treatment to nil-values when they are put into interfaces just seem wrong to me. They single out nil-values as somehow special or less valid than other values. They single out pointer/slice/map/chan types as somehow special over int/bool/string/… types. It just seems undeniable to me, that they make the language *less* consistent.

If you ask my opinion, I would make interfaces compare to nil on just data pointer. If one wanted interface which doesn't require data, he could've easily created one with static stub variable. No additional checks, no "semi-nil" fat pointers, everything simple and consistent.

The rule is very simple: A nil-interface is one that has no dynamic value. All values are treated the same for this purpose. All types are treated the same. I don't understand how that is anything but simple and consistent. It might be less understandable for some other reason, but I don't think it's simplicity or consistency.

targe...@gmail.com

unread,
Aug 27, 2020, 6:53:06 AM8/27/20
to golang-nuts
> Even though I really don't understand why this isn't just one of those "you learn about it, you know about it, you never run into any problems again" type of things.

Because you then must remember about this specific case every time you cast potentially nil pointer variable to interface. Every time you must write `if x != nil { return x; } else { return nil; }` instead of just `return x;` Does this make language simpler?

> But solutions that try to give special treatment to nil-values when they are put into interfaces just seem wrong to me.

Because nils or null pointers are indeed special. They mean "Points to no data". So dereference operation on such pointer leads to exceptional state. In fact, nullable pointer in terms of richer type systems is a sum-type `nil|*T` where `*T` always points to some valid object, and thus dereferencing it is valid. map/slice/chan types are pointers in disguise. By the way, AFAIK string isn't "special" here because "" and nil are treated equally. As for comparison to int/bool, you can safely perform all the operations on 0 the same way as on non-zero integers, except dividing by it. Same for `false`. nil can be vaguely compared to floats' NaN - except NaN is a potential (albeit rare) result of any operation on floats, while pointer cannot become invalid through dereference.

> The rule is very simple: A nil-interface is one that has no dynamic value. All values are treated the same for this purpose. All types are treated the same. I don't understand how that is anything but simple and consistent. It might be less understandable for some other reason, but I don't think it's simplicity or consistency.

Please don't forget that interface pointer isn't simple. It's a so-called "fat pointer" which consists of pointer to data and pointer to methods table. Thus, we have 4 potential states - (nil, nil), (nil, pointer), (pointer, nil) and (pointer,pointer). First one is just ordinary nil interface. Last one is just ordinary interface pointer with all operations callable without issue (as long as they're properly implemented, of course). Third one with valid data pointer and nil table pointer can be AFAIK created only through reflection and is safely considered "invalid state". We're left with second state with nil data pointer and valid table pointer, making interface methods callable on it. It wouldn't be a problem - if such state couldn't be created by merely casting typed nil pointer (typed pointer variable with nil value) to interface. Why is this an issue? Because most interface implementations require valid data pointer. "Static" (i.e. not needing data) implementations can be considered corner case.

So if we're hypothetically designing language with such fat pointers, how can we solve this issue?

One way is golang's way, where interface is nil when both components are nil. In such case, implicit casts mentioned above can easily lead to invalid state. To circumvent this, such state (nil, pointer) is better created only explicitly, "I know what I'm doing".

The other way is to check interface against nil only by its data pointer. When it's created from typed pointer, it always gets valid table pointer and data pointer from original typed one. When it's compared to nil, it's compared only with its data pointer. Thus, nil translates to nil, and we avoid second Shroedinger's state. If we wanna static implementation, we just create static variable which is `struct{}` and return pointer to it. Alas, this approach is no-go because it involves breakage too deep.

Robert Engels

unread,
Aug 27, 2020, 6:55:54 AM8/27/20
to Axel Wagner, targe...@gmail.com, golang-nuts
This will be a Go wart that will never go away. All languages have warts. This one just happens to be on the top of the index finger  There is so little utility in a nil interface but it’s there. 

On Aug 27, 2020, at 5:14 AM, 'Axel Wagner' via golang-nuts <golan...@googlegroups.com> wrote:



targe...@gmail.com

unread,
Aug 27, 2020, 7:01:33 AM8/27/20