-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: Go 2: use an identifier other than nil for uninitialized interfaces #24682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Could you clarify how this proposal differs from #22729? Note in particular point (5) of @ianlancetaylor's proposal:
|
Yes, it’s a strict subset. Considering that the other proposals all gained criticisms for aspects that go beyond this particular subset, I believe it’s better to propose a minimal version that focuses on the IMHO essential part. |
Here is an attempt at showing that this proposal objectively improves the language. Consider the following code fragment: v = nil
w = v
if w == nil {
fmt.Println("no")
} else {
fmt.Println("yes")
} Without the proposal above, this code fragment is ambiguous: You need to know the type of the variable With the proposal above, variables of interface types are not allowed to be compared to v = nil
w = v
if w == nil {
fmt.Println("no")
} else {
fmt.Println("yes")
} Here, Alternatively: v = nil
w = v
if w == {} { // or null, or nilinterface, etc.
fmt.Println("no")
} else {
fmt.Println("yes")
} Here, I'm not arguing that this particular example occurs often (it's artificial, so it probably doesn't). I'm also not arguing that it's hard to find out what the types of variables are (with a good IDE probably just hovering the mouse cursor over the variable name, without a good IDE scrolling to some other place in the code). I'm nevertheless arguing that this is nevertheless an improvement, and that in fact Go should have been designed like this from the beginning. I also believe that the change shouldn't cost much, because the compiler has to know about the different roles of |
#24635 is a related but completely different and orthogonal issue. #21538 combines the proposal discussed here and #24635 (which is unnecessary, because they address different issues, so it's good that #21538 was closed). #22729 goes a lot further than the proposal discussed here. As with #21538, it combines solutions to related, but essentially different problems, IMHO. |
I can't say that I am sanguine about
We will see a great deal of code like
It doesn't correspond to anything else in the language. I think a predeclared identifier is more feasible, but as the discussion in #22729 shows picking that identifier is not straightforward. Separately I note that even though Go 2 can break language compatibility, it must still be largely backward compatible. Requiring every line of the form
to change would be quite drastic. I think it's infeasible without a transition plan. |
This proposal is not about syntactic choices. It doesn't have to be |
We can't just wave away the choice of identifier. This is going to appear a lot in Go code. The name matters.
|
(An interesting thought experiment: what if they were equal?) |
About the syntax: I agree by now that My preference by now would be About a transition plan: I don't believe the change is that drastic. With this particular proposal (24682), |
This is a subset of #22729, which has plenty of discussion. Closing this issue in favor of that one. |
This is a variation of #21538 with a very important difference (see below). It's also related to #22729 and #24635.
It's confusing that nil can be used both as a value to represent an uninitialized interface, and as a value for the pointer that an interface is initialized with. This is a stumbling block for people new to Go, but also trips up experienced developers every now and then.
Proposal: use a value other than nil for uninitialized interfaces. To avoid adding new pre-defined identifiers, the value could be syntactically represented as {}, for example, but it may also be ok to introduce a new identifier, like null or nilinterface, or some such. This means testing for an uninitialized interface would have to be expressed like this:
With this proposal, tests against nil (like in
v != nil
) are not allowed anymore. This proposal explicitly does not suggest to add a way for testing for typed nil pointers stored in interfaces in any way. (If you prefer such a feature, refer to one of the other proposals mentioned above, or submit a separate, potentially complementary proposal.)Rationale: A lot of people seem to be strongly opposed to adding a way to allow for testing for typed nil pointers being stored in an interface variable other than through the reflect package, and strongly encourage people to call methods instead that are supposed to handle nil pointers gracefully. I still strongly believe the language is improved if interface variables are simply not comparable to the nil identifier anymore at all to make that distinction even more explicit, and ensure that developers don't falsely believe they compared to any other possible meaning of nil.
This proposal implies a change that is not backwards compatible, but it should be easy to write a tool that automatically converts programs since a type checker should be able to detect the relevant cases.
The text was updated successfully, but these errors were encountered: