On Thu, Aug 27, 2020 at 11:10 AM targe...@gmail.com <target....@gmail.com> wrote:
> it would definitely. Though price for consistency looks very much > acceptable. I don't think "consistency" is at all the right word here. If anything, things would get *less* consistent, not more. > Personally, I would also find it very confusing, if converting a T to a T > changed program behavior > Sorry, didn't get it. Are you saying that nil pointer -> nil interface is > more confusing? > 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. > On Thursday, August 27, 2020 at 11:49:16 AM UTC+3 > axel.wa...@googlemail.com wrote: > >> On Thu, Aug 27, 2020 at 10:06 AM targe...@gmail.com <targe...@gmail.com> >> wrote: >> >>> 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. >>> >> >> This would require to insert extra nil-checks when assigning a >> pointer-value to an interface, as the compiler can't know if a pointer is >> nil or not. Personally, I would also find it very confusing, if converting >> a T to a T changed program behavior (though arguably, there is one such >> case currently with `uintptr(uintptr(unsafe.Pointer))`. But usage of >> `unsafe` seems sufficiently advanced). >> >> >>> >>> On Monday, August 24, 2020 at 7:08:17 AM UTC+3 alex.be...@gmail.com >>> wrote: >>> >>>> Can we at least move with the https://github.com/golang/go/issues/22729 >>>> , please? Anything will help with the current mess. >>>> >>>> >>>> On Sunday, August 23, 2020 at 8:52:30 PM UTC-7, Ian Lance Taylor wrote: >>>> >>>>> On Sun, Aug 23, 2020 at 1:16 PM Denis Cheremisov >>>>> <denis.c...@gmail.com> wrote: >>>>> > >>>>> > You may use something like this >>>>> > >>>>> > value2 := >>>>> *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer(&value)) + 8)) >>>>> > if value2 == 0 { >>>>> > return true >>>>> > } >>>>> > >>>>> > on AMD64, should work also for any 64 bit architecture (at least I >>>>> believe so). Remember though this is hacky and may stop working once. >>>>> >>>>> You could do that, but please don't. >>>>> >>>>> Ian >>>>> >>>>> >>>>> > воскресенье, 23 августа 2020 г. в 22:58:51 UTC+3, Aviv Eyal: >>>>> >> >>>>> >> I was trying to show that the current behavior is confusing and >>>>> that fmt.Print() needing to resort to panic-and-recover is kinda code >>>>> smell, but I sorts-of convinced myself that the current behavior is right, >>>>> or at least consistent. >>>>> >> >>>>> >> In my code, I got bit because I sometimes use v *Type to denote "I >>>>> may or may not have a value here" (where Type is a value-type). >>>>> >> This is probably a bad practice on my behalf, because I break the >>>>> Liskov substitution principle: there is a value of `*Type` that is not a >>>>> valid value of `Type`, and I let this value slip by. >>>>> >> >>>>> >> In this case, `v Type` implements Stringer (i.e. valid callee for >>>>> `v.String()`, but `v *Type`, in the strictest sense, does not. >>>>> >> The only reason we can write: >>>>> >> >>>>> >> func (Type) String() string {...} >>>>> >> v *Type = &Type{...} >>>>> >> _ = v.String() >>>>> >> >>>>> >> and have it compile, is syntactic sugar: `v` gets implicitly >>>>> de-referenced, and there's an implicit assumption that it's not nil. >>>>> >> And there's a matching syntactic sugar for converting `Type` to a >>>>> `*Type`. >>>>> >> >>>>> >> So, In the code: >>>>> >> >>>>> >> func (Type) String() string {...} >>>>> >> >>>>> >> v *Type = nil >>>>> >> r interface{} = v >>>>> >> _, ok = r.(Stringer) >>>>> >> >>>>> >> What I really want to ask is "Can I, at runtime, call r.String()?", >>>>> whereas the question Go answers is "Is any of `r`, `*r`, or `&r` defines >>>>> .String()?" - which matches the static semantics of `r.String()`. >>>>> >> >>>>> >> So, while I should probably not use *Type as a replacement for >>>>> Optional<Type>, I think it might make sense to have some operator that can >>>>> determine, at run-time, if a call `r.String()` is valid (including a >>>>> nil-check). >>>>> >> >>>>> >> >>>>> >> -- Aviv >>>>> >> >>>>> >> On Saturday, April 11, 2020 at 4:48:28 PM UTC+3 >>>>> ren...@ix.netcom.com wrote: >>>>> >>> >>>>> >>> I agree with the OP. The usefulness of nil interfaces is pretty >>>>> limited. Show me a useful case that cant easily be implemented with >>>>> non-nil >>>>> interfaces. >>>>> >>> >>>>> >>> I would argue that allowing nil interfaces causes more subtle >>>>> latent bugs and makes it harder to reason about the correctness of code >>>>> when reviewing it. >>>>> >>> >>>>> >>> It just feels wrong. I realize I’m probably in the minority here >>>>> but the OP is not alone. >>>>> >>> >>>>> >>> On Apr 11, 2020, at 8:20 AM, 'Axel Wagner' via golang-nuts < >>>>> golan...@googlegroups.com> wrote: >>>>> >>> >>>>> >>> On Fri, Apr 10, 2020 at 7:17 PM <cpu...@gmail.com> wrote: >>>>> >>>> >>>>> >>>> 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. >>>>> >>> >>>>> >>> >>>>> >>> Let's imagine a world in which `foo == nil` also is true if `foo` >>>>> is an interface-value containing a nil-pointer. Let's say in this world, >>>>> someone sends a message to golang-nuts. They wrote a mock for the same >>>>> code. And since it's just a mock, they just returned static value from its >>>>> methods and didn't need to care if the pointer was nil or not. They are >>>>> confused, because the passed in this mock, but the code just assumed the >>>>> field was uninitialized and never called into their mock. What would you >>>>> tell them? Why is their confusion less valid? >>>>> >>> >>>>> >>>> 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. >>>>> >>> >>>>> >>> >>>>> >>> In the code you posted, even a nil *other is a perfectly fine >>>>> implementation of fooer. You can call `(*other)(nil).foo()` without any >>>>> problems. >>>>> >>> So, as you illustrated, calling methods on a nil-pointer can be >>>>> totally fine. A nil-interface, OTOH, doesn't have any methods to call, as >>>>> it doesn't contain a dynamic value. If you write `(*other)(nil).foo()`, it >>>>> is completely clear what code gets called - even if that code *might* >>>>> panic. If you write `fooer(nil).foo()`, what code should be called in your >>>>> opinion? >>>>> >>> >>>>> >>> I think it's easy to see that a nil-interface and a nil-pointer >>>>> stored in an interface are very different things. Even from first >>>>> principles, without deep knowledge of the language. And if they are >>>>> obviously different, I don't understand why you'd find it confusing that >>>>> they are not the same in this particular manner. >>>>> >>> >>>>> >>>> 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. >>>>> >>> >>>>> >>> >>>>> >>> I fully agree with that. What I *don't* agree with, is where you >>>>> attribute the problem here. You say, the problem is that the nil-check is >>>>> ill-behaved. I say that - if anything - the original nil-assignment is >>>>> ill-behaved. Having `(fooer)((*other)(nil)) == nil` be true is >>>>> semantically >>>>> wrong, because by checking against `nil`, you are checking if you have a >>>>> correct implementation - and you might well have a correct implementation, >>>>> even if it's using a nil-pointer. >>>>> >>> >>>>> >>> Note, that the contained pointer being nil isn't the *only* case >>>>> in which calling the method might panic. For example, what about this >>>>> code? >>>>> >>> https://play.golang.org/p/lNq0qphez7v >>>>> >>> Shouldn't the `nil`-check also catch that? After all, calling the >>>>> method panics, so it's clearly not a valid implementation - even if x >>>>> itself is not nil. Why is a nil-pointer more special than any other value >>>>> that causes a method to panic? >>>>> >>> >>>>> >>>> Seems as of today that there is no tooling to support that check. >>>>> Maybe it's not a widespread issue. >>>>> >>> >>>>> >>> >>>>> >>> As of today, the language also isn't changed :) Maybe someone who >>>>> think this is important enough to change the language, could also feel >>>>> it's >>>>> important enough to write this tooling. >>>>> >>> >>>>> >>>> >>>>> >>>> -- >>>>> >>>> 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. >>>>> >>>>> >>> >>>>> >>> -- >>>>> >>> 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/CAEkBMfEPjcsZ3enqXyt%2BUphFJ1cNQ81cFCcjfwwkQZKHMrjSzA%40mail.gmail.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 golan...@googlegroups.com. >>>>> >>>> > To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/golang-nuts/c1ed2e38-6215-4ed2-8357-f8b5d83bf1a7n%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/84244528-84e6-4c2e-89bf-7fbf0590e132n%40googlegroups.com >>> <https://groups.google.com/d/msgid/golang-nuts/84244528-84e6-4c2e-89bf-7fbf0590e132n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > 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+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/46d92421-a3a8-4b8a-b557-aa14d79e55b6n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/46d92421-a3a8-4b8a-b557-aa14d79e55b6n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfH8tcDsXqXNuG9%3Diw0%3D05Jx0vyre9okJNMJORcBgT7weQ%40mail.gmail.com.