-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
proposal: Go 2: Add typednil
keyword for checking whether an interface value is a typed nil.
#24635
Comments
I agree with @jaekwon that a simpler proposal than #22729 should be preferred. In #22729, a lot of additional identifiers are added, but most cases of ambiguities between different uses of ‘nil’ are already caught by the static type checker, so I don’t think it’s necessary to add these additional identifiers. The case of an empty-interface nil vs. a typed nil is the only case that is ambiguous, as far as I can tell, and is not caught by the type checker, and can therefore lead to confusing results that are potentially only caught later in testing or even after deployment. So I think a proposal that solves this particular case only is simpler and preferable. However, I don’t agree with @jaekwon that a typednil is a good solution, because it doesn’t prevent the potentially erroneous ‘v == nil’ test when v is of an interface type, so doesn’t help in solving the issue that bugs may be lurking in code until testing or later. For this reason, I still prefer my suggestion in #21538. I’m not picky about the syntax, though, it can be my suggestion {}, or null, or nilinterface, or something else. What is more important to me is the semantics. |
The fundamental objections raised in #21538 and elsewhere remain unaddressed. If you shouldn't care about the specifics a caller chooses to implement an interface in the first place, why make it any easier to do? In my opinion, the desire to put this weird constraint on interface values doesn't indicate a flaw in the language that needs to be fixed but rather points to a potential issue with your use of interfaces. These details are up to the implementor of the interface to decide, not on its users. If you want to provide special behaviour for a particular implementation, use a type assertion. Otherwise, you just assume that the passed value is a correct implementation of the interface contract. Using weird heuristics like "is not a nil value" or "is an integer value equal to 42" on the contained value won't do any good here. |
typednil
keyword for checking whether an interface value is a typed nil.typednil
keyword for checking whether an interface value is a typed nil.
This proposal is missing background information. What concrete problems is it intended to address? (Some illustrations or experience reports would be helpful.) |
typednil
keyword for checking whether an interface value is a typed nil.typednil
keyword for checking whether an interface value is a typed nil.
This clearly relates to @davecheney's experience report, but I think there is something missing from the story: where does the proposed typed-nil-check occur, and why? (That is, what are some concrete call sites where you would actually use this check?) In particular: if the |
This came about while implementing Amino, an encoding system inspired by Protobuf3. I could find the exact place where it caused an issue, but it seems to apply to encoding libraries in general. For example, using encoding/json as the example, https://golang.org/pkg/encoding/json/#Encoder.Encode func (enc *Encoder) Encode(v interface{}) error Here, we do care about "the specifics a caller chooses to implement an interface in the first place", because that's what codecs should care about. Or put another way, Golang objects are for more than conceptual-interface-implementations, or its "function". Sometimes what's more important is the form of the object, regardless of its function or how it's referred to. Amino takes this to its logical conclusion, and handles interfaces/concrete-types natively, and makes for a really nice codec. To focus only on Golang's awesome interface system is to ignore a crucial aspect of the language, imo. Go2 should marry both form and function well. |
@pcostanza I like your reasoning as well. I wonder how difficult the migration will be. If migration is easy, I agree with your proposal 100%. |
For the specific case of For those use-cases, it seems like the only benefit of moving the check out of For other kinds of codecs, particularly involving generated code, it often makes sense to define a reflection API for the generated code rather than relying on Go's `reflect' package (see golang/protobuf#291 and golang/protobuf#364). So I still don't really understand the concrete use-case. Some examples of how it would be used in existing code would be helpful. |
The big difference between using reflection and using a native operator (e.g. == typednil) is that the latter implies a commitment by the language to ensure that the operation is fast. I believe it's within Go's design philosophy to ensure that what appears like a simple operation, is a simpler operation. I haven't done any benchmarking recently so, there's that disclaimer. A bit busy now, maybe someone else can jump in and provide some numbers, perhaps disproving my point above. @odeke-em |
If you're using reflection anyway, what matters is whether the reflective operation is fast — not the built-in one. (For example, That's why I'm interested in concrete examples: I suspect that the vast majority of them would not benefit from the built-in operations. Evidence either way would be helpful. |
There is a problem with |
I believe the performance discussion is a red herring. There are enough known implementation techniques for efficiently implementing reflection. (For example, a compiler can have built-in translations for what looks like regular reflective API calls, perform partial evaluation, etc.) The important question, I believe, is: Should you have to import the Since the proposal discussed here doesn't actually add anything beyond what you can already do in Go, I believe it is less important than the issue discussed in #24682, which I believe objectively improves the language. |
I'm not sure it objectively improves the language.
You already can check if a pointer contains a nil value, but you have to know its type.
Why must a pointer have a special case? It needs a better use case than a small snippet of code. Edit: I've mixed up issue #24682 with #24635. I do like the issue #24682 try to address but I still feel uneasy with the special case it adds. |
@champioj I apologize for bad wording. I believe #24682 objectively improves the language, not the proposal discussed here. (Your edit suggests that you understood this later, but I should have worded this clearer from the start.) I understand the uneasiness, but #24682 doesn't actually add a special case. The treatment of |
If the only problem this solves is a performance problem, then we aren't going to do it. We aren't going to introduce a new language feature only to avoid a type assertion or a function call. |
We aren't going to add this. |
Following from this proposal: #21538, I think an alternative proposal would be to "simply" introduce a new keyword called
typednil
. It can only used for comparison, and it would have behavior identical to the following code:This way, the current
nil
keyword behavior is preserved -- a zero value for interfaces as well as channels, funcs, maps, pointers, and slices, but we could now do the following:The text was updated successfully, but these errors were encountered: