--
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.
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.
I sincerely hope Go 2 will have it fixed.
--
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.
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.
--
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.
--
--
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.
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
But this crashes when foo is really a nil pointer to a type which does support Stringer.
func isNil(a interface{}) bool {
defer func() { recover() }()
return a == nil || reflect.ValueOf(a).IsNil()
}
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.
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
}
}
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).
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.
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.
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.
Seems as of today that there is no tooling to support that check. Maybe it's not a widespread issue.
--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEPjcsZ3enqXyt%2BUphFJ1cNQ81cFCcjfwwkQZKHMrjSzA%40mail.gmail.com.
> To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/84244528-84e6-4c2e-89bf-7fbf0590e132n%40googlegroups.com.
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 behaviorSorry, didn't get it. Are you saying that nil pointer -> nil interface is more confusing?
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/46d92421-a3a8-4b8a-b557-aa14d79e55b6n%40googlegroups.com.
> 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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/31df134b-7e55-4f32-9e1f-6d974817891en%40googlegroups.com.
On Aug 27, 2020, at 5:14 AM, 'Axel Wagner' via golang-nuts <golan...@googlegroups.com> wrote:
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfGhDrbJRMr%3DtxPu_XNDTzyT7PV61Oo7kOLP5QBqg-Zaiw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/f3081a9b-bf99-41f9-81e6-62147cbb6a12n%40googlegroups.com.
To me, if `x == nil` and then `y != nil` after `y = x` is much more confusing.
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;`
> 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
> 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
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
One way […]. The other way […]
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/4613df4c-9342-4285-9b8d-823afa82f58en%40googlegroups.com.
On Thu, Aug 27, 2020 at 6:12 AM 'Axel Wagner' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> On Thu, Aug 27, 2020 at 12:53 PM targe...@gmail.com <targ...@gmail.com> wrote:
>>
>> 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;`
>
>
> This is true, but that alone is not indicative of a problem. You have to remember that `select` does a pseudo-random selection of cases everytime you use it, that you can't write to nil-maps, that dereferencing a nil-pointer might panic, that an index-expression might panic, that integer-addition might overflow, that floating-point math has counter-intuitive edge-cases, that init-functions run before main… you have to remember a *lot* of things every time you need them.
>
> I don't want to sound dismissive (as I said, I do think there is obviously *some* problem) but I don't run into cases where I would even be *tempted* to do this. Like, in your example, you'd need to a) have a declared pointer, b) would need to be oblivious to the fact on whether or not it's nil and c) it would have to be an invalid value if so and d) it would have to be a problem not caught by other means (e.g. returning a non-nil error alongside it). And when I am tempted to do this, I just know that the interface value will still be non-nil. And even when I don't, the most trivial of testing catches the problem.
>
> Like, I'm not saying it *never* happens or even that it never happens *to me*. But it seems very rarely cause significant problems and I don't understand why people put it so high up their list of being confusing or hard to remember.
I saw this happen mostly after refactoring code to replace structs
with interfaces. Functions start returning interfaces instead of
concrete types, and there is no obvious indication in the code that
might alert the potential problem.
On Aug 27, 2020, at 12:11 PM, Jake Montgomery <jake...@gmail.com> wrote:
--
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/99a93de9-5dbc-474a-b0c9-906a8ae2cbaeo%40googlegroups.com.
What would be the meaning of "none" interface?
It doesn't solve issue at hand. The issue is, conversion from typed nil pointer to interface results in non-nil interface with valid vtable pointer and nil receiver.
And only limited set of specifically crafted implementations supports nil receiver.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0ed95322-2b0c-4374-ab3c-3c68759e9ba5n%40googlegroups.com.