Hacker News new | ask | show | jobs
by nie 3234 days ago
I enjoyed the blog article and I would like to gently reiterate the notion that a _typed nil_ in Go 2 would change the semantic of _nil_, as seen in the example expression at the end of the article:

    var b *bytes.Buffer
    var r io.Reader = b
    fmt.Println(r == nil)
We might need to use other expressions to capture the _nil_ type of above assignment but we should enable the _value only_ equality check with `r == nil`
1 comments

Can someone point me to some examples where checking that the type of an interface is nil?

I have thought a bit about it but I couldn't come up with good situations.

"the type of an interface is nil" is that even possible?
Yes. The interface holds the concrete type of the value, if there is no concrete type it will be nil, so if you assign a nil to an interface-typed variable directly, you'll have a (nil, nil). If you first assign the nil to a pointer type T then assign/convert that to an interface type, you'll get (* T, nil). Here's a trivial demo:

    var a interface{} = nil // (nil, nil)
    var b *int = nil
    var c interface{} = b // (*int, nil)
    fmt.Println(a == c)
Of course most such cases are not that trivial, rather they're cases where a function takes an interface-valued parameter and checks for (param == nil), if the caller passes in an actual object there's no problem, if they pass in a concrete value no problem, but if they extract the nil literal to a concretely-typed context (variable) things go pear-shaped to various levels of fuckedness (depending what is done in the other branch).

And that's vicious because something as seemingly innocuous as "extract variable" on an immutable literal can break your code.

thanks for the example. so the answer to @dullgiulio question could be done by using reflection:

    var a interface{} = nil // (nil, nil)
    fmt.Println(reflect.TypeOf(a) == nil)
Thank you for your answer. I was writing from the phone and didn't make myself clear. My question is: what are the legitimate use cases for interfaces that are half-nil?

Ignoring the compatibility guarantee for the sake of discussion, I feel that nobody would notice if the compiler tomorrow started short-circuiting the equality check of interfaces against nil to return true if either tuple value is nil. But maybe I'm missing some use-case.

> My question is: what are the legitimate use cases for interfaces that are half-nil?

I think that's two different questions:

* Is there a legitimate use case for nil not being nil? I don't think so.

* Is there a legitimate use case for having "typed nil" interfaces? Kinda, Go supports and encourages calling methods "with nil receivers", and doing that through an interface requires that the concrete type (the non-nil half) be conserved otherwise you can't dispatch the method call.

Yes it is. An interface is basically a struct of the concrete type and the value. While the outer interface value still has a type, if no value was assigned to it, the concrete type field is still nil.
That, in fact, is the normal case which is why people are surprised by typed nils.

For example:

    func returnsNil() error { return nil }

    x := returnsNil()
    // x is of type nil and value nil.
My question misses the important words "a situation where it makes sense."

As I wrote below:

Ignoring the compatibility guarantee for the sake of discussion, I feel that nobody would notice if the compiler tomorrow started short-circuiting the equality check of interfaces against nil to return true if either tuple value is nil. But maybe I'm missing some use-case.