I'm trying to solve the eternal "interface == nil" problem and I can't find a solution in this case: https://go.dev/play/p/DSik2kJ-gg4
It looks like casting to the base pointer type confuses the reflection package. Is there a way to solve this?PS: PLEASE do add "nilptr" to the language proper.
--
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/469b88b2-6d64-4bcd-8b92-18f9781c4fd3n%40googlegroups.com.
Nope. Your solution doesn't work either: https://go.dev/play/p/DSik2kJ-gg4 (it doesn't crash, just falsely returns 'false').
What I'm trying to check is pretty straightforward: do I get the nil value passed to a function.
All types are completely valid, the structure is correctly cast to the base interface type and its methods can be safely called: https://go.dev/play/p/xseNiCSB0uAI don't see anything "uninteresting" in that. In a real program the interface is simply passed through an intermediate function, so I can't use an exact type.
That's a stupid part of the language and there's no good justification why this hasn't been yet fixed.
--On Wednesday, March 16, 2022 at 10:36:48 AM UTC-7 axel.wa...@googlemail.com wrote:On Wed, Mar 16, 2022 at 6:21 PM Alex Besogonov <alex.be...@gmail.com> wrote:I'm trying to solve the eternal "interface == nil" problem and I can't find a solution in this case: https://go.dev/play/p/DSik2kJ-gg4ISTM that you are discovering why this check just is not an interesting check to make in the first place.There is no meaning you can assign to "is the dynamic value of a non-nil interface nil", as `nil` might not even be a valid value for its dynamic type. It's also not a *helpful* check, because even non-nil pointers can cause a panic, if you call an associated method on them.You *can* write a check to see if a value contains a pointer relatively easily using reflect:But it's not a very useful check, unless you specifically want to work further with the pointer using reflect (e.g. how json.Unmarshal stores a value in a pointer).It looks like casting to the base pointer type confuses the reflection package. Is there a way to solve this?PS: PLEASE do add "nilptr" to the language proper.--
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/469b88b2-6d64-4bcd-8b92-18f9781c4fd3n%40googlegroups.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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/75f9517f-c6ea-4a93-8c88-d1293b5c8c0en%40googlegroups.com.
On Wed, Mar 16, 2022 at 7:02 PM Alex Besogonov <alex.be...@gmail.com> wrote:Nope. Your solution doesn't work either: https://go.dev/play/p/DSik2kJ-gg4 (it doesn't crash, just falsely returns 'false').That's your original code. I assume, though, you are trying to demonstrate that this doesn't return `true` when passed a nil-slice/func/chan/map. That's by design - the function does what it is designed to do, check if an interface value contains a nil-pointer. If you want something else, write a different function.
What I'm trying to check is pretty straightforward: do I get the nil value passed to a function.The way to check that is `return v == nil`. What you seem to be interested in is "I want to write a function which checks if the dynamic type of a function is a pointer, slice, channel, function or map type and if so, returns if the dynamic value is nil". You can write that easily enough.
On Wednesday, March 16, 2022 at 12:29:07 PM UTC-7 axel.wa...@googlemail.com wrote:On Wed, Mar 16, 2022 at 7:02 PM Alex Besogonov <alex.be...@gmail.com> wrote:Nope. Your solution doesn't work either: https://go.dev/play/p/DSik2kJ-gg4 (it doesn't crash, just falsely returns 'false').That's your original code. I assume, though, you are trying to demonstrate that this doesn't return `true` when passed a nil-slice/func/chan/map. That's by design - the function does what it is designed to do, check if an interface value contains a nil-pointer. If you want something else, write a different function.I don't believe that's true. The function is passed an interface (Tester) that has a nil pointer part but a non-nil type. That type also happens to be a struct with an embedded pointer to another struct that implements the interface.Here's a simplified version of the real code: https://go.dev/play/p/8LfgIGhd8GR - it compiles without any issues.
Except that you can not. In my case I have an interface that has the nil data part, and the program crashes because the reflect code doesn't know that I'm accessing the interface.
You can check my example, if you remove the nil check and use non-nil parameters, it would work just fine.
--
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/70a80a76-44b5-4af3-9eb5-2d8794e4d3c4n%40googlegroups.com.
Here's a simplified version of the real code: https://go.dev/play/p/8LfgIGhd8GR - it compiles without any issues.Yes it compiles. Plenty of buggy Go code will compile. Here is another example of buggy interface-based code which compiles just fine. We can't prevent users from writing buggy code.
It seems in this case, the bug is storing such a value in that interface. The solution is to not do that.
Note that in your case, the dynamic value of that interface is not nil. It's a struct value. Structs can not be nil.
S
contains an embedded field *T
,
the method sets of S
and *S
both
include promoted methods with receiver T
or
*T
."Except that you can not. In my case I have an interface that has the nil data part, and the program crashes because the reflect code doesn't know that I'm accessing the interface.The reflect code panics, because you are comparing a struct value to nil. Struct values can not be nil.
Again, just write different reflect code then.
Reflect gives you the capability to write any dynamic check you want. If you want to check that an embedded pointer field is not-nil, then write the reflect code to check for that. I don't really understand what you are trying to check. But you can implement whatever heuristic you want, using reflect.
But really, the solution here is not to "check better". It's to not store invalid implementations of an interface in the interface.
There *are* valid uses for this check - json.Unmarshal is one such. But those cases need reflection anyway. So reflect is a far more sensible and flexible way for programmers to implement whatever check they need, than changing the language.
You can check my example, if you remove the nil check and use non-nil parameters, it would work just fine.Okay. Then it seems you have your solution - "remove the nil check and use non-nil parameters”.
This is not a buggy code. This is a buggy language spec.
No. The bug is in Go’s spec that treats values and pointers differently when coercing values to an interface type.
Note that in your case, the dynamic value of that interface is not nil. It's a struct value. Structs can not be nil.Incorrect. Go language allows coercing a struct with an embedded pointer to an interface.
The reflect code panics, because you are comparing a struct value to nil. Struct values can not be nil.No. I’m comparing AN INTERFACE, not a struct.
The interface’s provenance is _through_ a struct that has an embedded pointer, but this should not matter to the code that accepts the interface.
Would you argue that these statements should behave differently: '1 + 1 == 2’ and ‘2 == 2’? Because you argue that ‘1 + 1’ is not ‘2’ and should not work this way.
Again, just write different reflect code then.Which? Go seems to be losing the type of the variable. It’s not possible to say “get me a value as THIS interface type”.
I’m trying to check that a freaking interface pointer part is nil. That’s it.
But really, the solution here is not to "check better". It's to not store invalid implementations of an interface in the interface.I gave you the real example, somewhat simplified.
Not feasible. It would require huge amounts of code in call sites.Okay. Then it seems you have your solution - "remove the nil check and use non-nil parameters”.
The reflect code panics, because you are comparing a struct value to nil. Struct values can not be nil.No. I’m comparing AN INTERFACE, not a struct.You are using `reflect` to inspect the dynamic value of that interface. That dynamic value is a struct.
The interface’s provenance is _through_ a struct that has an embedded pointer, but this should not matter to the code that accepts the interface.I completely agree with this. That's why it is so important not to store invalid values in an interface. The code using that interface has no reasonable way to check if the value is valid. So it has to rely on the caller to only provide valid implementations.
But really, the solution here is not to "check better". It's to not store invalid implementations of an interface in the interface.I gave you the real example, somewhat simplified.
Then this is the real example with the fix applied: https://go.dev/play/p/04H1KenHjRV
Note that in your case, the dynamic value of that interface is not nil. It's a struct value. Structs can not be nil.Incorrect. Go language allows coercing a struct with an embedded pointer to an interface. Spec:"IfS
contains an embedded field*T
, the method sets ofS
and*S
both include promoted methods with receiverT
or*T
."
No. It should be a POINTER to a struct, which would have been fine. Instead Go's reflection incorrectly latches on the type of the embedding structure.
The code is NOT using anything incorrect.
The interface is obtained through a pointer to a struct, which is completely valid. The only problem is that this pointer is embedded inside a struct.If you rewrite the code to use a named field, it would work. This means that the language behaves differently depending on a field having a name.
The real example would look like this: https://go.dev/play/p/mwUfh4_RBUU - you do see why it's a tad problematic?
--
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/58d5770b-4888-4980-8f9e-c96310d57490n%40googlegroups.com.
The real example would look like this: https://go.dev/play/p/mwUfh4_RBUU - you do see why it's a tad problematic?