On Sun, Aug 23, 2020 at 1:16 PM Denis Cheremisov
<[email protected]> 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 [email protected] 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
>>> <[email protected]> wrote:
>>>
>>> On Fri, Apr 10, 2020 at 7:17 PM <[email protected]> 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 [email protected].
>>>> 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 [email protected].
>>>
>>> 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 [email protected].
> 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcUBtDbk8Nb49r-5OQ%2Bi3wthExBm9CR4ZdHDkYfqdBzUEA%40mail.gmail.com.