Hacker News new | ask | show | jobs
by rowanseymour 239 days ago
I don't know why every time people complain about this there is an assumption that we just don't understand why it is the way it is. I get that x can implement X and x can have methods that work with nil. I sometimes write methods that work with nils. It's a neat feature.

What's frustrating is that 99.99% of written go code doesn't work this way and so people _do_ shoot themselves in the foot all the time, and so at some point you have to concede that what we have might be logical but it isn't intuitive. And that kinda sucks for a language that prides itself on simplicity.

I also get that there's no easy way to address this. The best I can imagine is a way to declare that a method Y on type x can't take nil so (*x)(nil) shouldn't be considered as satisfying that method on an interface.. and thus not boxed automatically into that interface type. But yeah I get that's gonna get messy. If I could think of a good solution I'd make a proposal.

1 comments

Because in the last dozen times I've handled this question the root cause is lack of understanding of why. Inductively it is logical to conclude that's the reason next time. It is probably also the case the bulk of readers of this conversation are still in the camp that don't understand the problem correctly.

If you understand that there isn't really a fix and just wish there was one anyhow, while I still disagree in some details it's in the range I wouldn't fuss about. I understand that sort of wishing perfectly; don't think there's ever been a language I've used for a long time that I've had similar sorts of "I just wish it could work this way even though I understand why it can't." Maybe someday we'll be "blessed" with some sort of LLM-based language that can do things like that... for better or for worse.

I can't think of good way to give programmers control over boxing without adding a bunch of complexity that nobody wants.. but it doesn't seem out of the realm of possibility that the linter could detect issues like this. It should be able to spot methods that aren't nil-safe and spot nil values of those types ending up in interfaces with those methods. Then you'd have less explaining to do!
It's a bit difficult statically because it is a flow sensitive analysis.

You are not wrong that it is a sharp edge. Completely removing nils from interfaces is not possible because: 1. not backward compatible

However I would nuance a little. Having an empty interface ie. a untyped nil is useful. Having typed nils in interfaces is arguable. Because every value type that has methods can make pointer. That means potential deref if any such pointer is passed to an interface variable instead of the value itself.

Being able to keep nil from some interfaces would be useful.

You're not wrong. In general there is not much value in having working methods on a typed nil pointer.

If we think in terms of bottom wrt type theory, yes it is supposed to implement every type. But that would be closer to untyped nil and that's not how go's type system works either. It is close though. We just don't have a language concept for nillable int because variables are auto initialized to 0. And because it would be difficult to encode such an information purely virtually. But that could be possible in theory, without mechanical sympathy. I digress. The takeaway is that I don't think a linter can do the trick easily but there has been good attempts. And it is worth pondering, you're right.

"empty interface" meaning an interface value that is empty i.e. nil interface... ofc
A perfect linter runs into the halting problem, I think, but a pretty-darned-good linter that would catch that methods on your pointer-based method doesn't do "something sensible" with nil would be pretty interesting to me. I think it could help train the community about this issue better than anything else.

I'm full up on tasks, though; even if I were writing a linter for Go that would not currently be my top goal, though it's definitely quite interesting overall.