3 ms·
Go has no such feature. Go's interfaces are a reference type which point to the runtime implementation. If that implementation is itself a pointer type, then th
by throwaway894345 5y ago
Go has no such feature. Go's interfaces are a reference type which point to the runtime implementation. If that implementation is itself a pointer type, then that pointer may also be nil. Any language that has nullable reference types (including languages in which everything is a pointer like Java or Python) will have this problem.
EDIT: would really like to know why I'm being downvoted. If you disagree with my comment, then best of luck to you in rebutting it. :)
- masklinn 5y ago> Go has no such feature. [...] Any language that has nullable reference types (including languages in which everything is a pointer like Java or Python) will have this problem. var i *int = nil var x interface{} = i if x != nil { fmt.Printf("%v was not nil", x) } <nil> was not nil By all means, do demonstrate how Java or Python have this problem.
- throwaway894345 5y agoSure: class Ptr: def __init__(self, x): self.x = x x = Ptr(None) if x != None: # Go's `%v` print directive unpacks interfaces. # We'll use `x.x` to emulate the same here print(f"{x.x} was not None")
- kinjba11 5y agoI don't really see a problem with that code - there is no confusion, `Ptr(None)` is clearly not `None`. Whereas var i *int = nil var x interface{} = i if x != nil { I assigned `nil` to `x` and yet `x` is not nil. Implicit conversions aren't unusual in programming but in Go they stand out a bit. The closest analog I could find was abusing implicit conversion operator in C#. But even that's pretty explicit and you can tell something odd is happening. Thing1 i = null; Thing2 x = i; if (x != null) { System.Console.WriteLine("x is not null"); } class Thing1 { public static implicit operator Thing2(Thing1 c) => new(); } class Thing2 {}
- throwaway894345 5y agoApologies in advance for the terse response—I’m in a hurry and on mobile. First of all, I’m not asserting that there isn’t a problem with Go. I’m asserting that its interfaces aren’t some three-state beast per the OP. Secondly, you don’t see the problem with the Python code because you’re not comparing it like for like with Go code. The equivalent Go code would look like this: `var x interface{} = (*int)(nil)` which is at least as conspicuous as the Python example. > I assigned `nil` to `x` and yet `x` is not nil. No, you put a nil pointer into an interface, thus the interface is not nil. We have to understand the semantics of the language we’re programming in—it’s not fair to criticize Go because it’s interfaces aren’t my exactly Python variables. I think there’s probably some valid criticism against Go with respect to the error-prone nature of its interfaces, but I don’t think it’s that they lack Python variable semantics. > Implicit conversions aren't unusual in programming but in Go they stand out a bit. This isn’t an implicit conversion, we’re explicitly putting an int pointer value (nil in this case) into an explicitly-typed interface{} variable.
- Joker_vD 5y agoIt's much worse, because there is auto-conversion between concrete types and interfaces you can't reliably do e.g. "if err != nil { SendString(err.Error()) }" ― it can panic with SIGSEGV. I've ran into it a month ago in actual production code: condensed version is at [0]. Yes, it's a bad design on the 3rd-party library's part... or perhaps it is a defect of the language: "pit of success" and all of that, you know? [0] https://go.dev/play/p/D_M1geUtJTP https://go.dev/play/p/D_M1geUtJTP
- throwaway894345 5y agoI don't think this is a different (and thus not "worse") case--it seems like a specific instance of the same case we've been discussing. Ultimately it comes down to this: error.Error((*CustomErrorType)(nil)) You're putting a nil `*CustomErrorType` into an `error` interface. This definitely causes some people confusion and results in bugs, but the question under discussion is whether the original claim ("an interface can be simultaneously nil and not nil") is true. Of course, it's not true as this example illustrates--the interface is not nil but the underlying data (of type `*CustomErrorType`) is nil.
- anonymoushn 5y agoI think the original claim is that it can be inner nil or outer nil and those are two different things and often you should check for both.
- throwaway894345 5y agoThe original comment was: > A great innovation of Go is that it includes a built-in reference type with both inner nils and outer nils. Which the OP later clarified by saying an interface can be both nil and not nil at the same time. So it’s pretty clear that we’re debating about whether interfaces have three states (nil, valid, and both) i.e., multiple kinds on nullity (inner vs outer).
- anonymoushn 5y ago