Live data from Hacker News

Excessive nil pointer checks in Go

konradreiche.com

31–40 of 116 posts

Re: Excessive nil pointer checks in Go

#31
A good point and the java ecosystem makes similar mistakes. In general any:

``` if (x != null && !x.isEmpty()) doAThing(x); ```

is either:

[A] Code directly on the boundary between systems; the other system is explicitly documented to treat null and empty as semantically equivalent, which is bad, but given that the mistake lies in a system beyond the control of this programmer, they're working around it. It can exist in this boundary code and nowhere else, or

[B] Extremely rare, but there is a real semantic difference between the notion 'x is null' and 'x is empty' but this code wants to do the same thing in both semantically separate cases, or

[C] it's bad code.

NPEs are better than endless defensive dealings. If code checks for null I'd expect that null has a semantically identifiable meaning, and one that isn't also covered by something else (such as some notion of 'empty', e.g. an empty string or an empty list).

Re: Excessive nil pointer checks in Go

#32

Earlier quoted context omitted.

Obviously, in his example it would be RateLimiter not Option , so no check necessary.

you still need to unpack that option somewhere.

_If_ you start out with an optional, and even then only once in the code path.

Re: Excessive nil pointer checks in Go

#33

Earlier quoted context omitted.

it does not resolve the problem. you would need to check "is this value optional?" and unpacking everywhere. this is what this article saying. you can do unpacking/nil-checks at the root or later when it happened. with rust you have 2x more ways to shoot yourself in the foot.

You check and unpack once, then the rest of the "positive" codepath can use the reference without fearing null. I fail to see how Rust would offer twice as many ways to shoot yourself in the foot ; this is a rather safe and picky language.

true, "non-nil pointers"/references will help here to avoid nil checks.

also true, if you have optional you still need to unpack it somwhere, and your nil checks become unpacking statements. delayed conditionals and delegation to callsites far from offending code (what author says) is still present.

and if you also have pointers, then you can do Optional.. and now you have to option unpakcing + nil checks. 2x more problems.

Re: Excessive nil pointer checks in Go

#34
Go is a very unique language in that it is the only language designed to make you understand the frustration of online dating.

First, seduction, and then as it reveals how little it cares about you, eventual disappointment.

Re: Excessive nil pointer checks in Go

#36

I could have forgiven nil checks, but nil checks on interfaces elevated nils to a whole new level, which is annoying, but I do get where they were going with this: you should never nil check an interface. After all,an interface could be valid for a nil value. There are ways to decently write go and not deal with nil, but as usual, linters defaults makes it impossible and you have to fight with your team before they w…

This suggestion fails for values that can be null, need to be mutable or need references from multiple places etc – it's not "just performance penalty". Go has a problem, "just remember to always do X, never Y" patterns can't be guaranteed across all libraries you use, can't be enforced, can be violated for good reasons, other patterns and as a mistake etc etc. Shame because otherwise it's a great language, but some…

The best approach is to use other programming languages with more open minded approach to modern type systems, and leave Go to the use cases where there is no alternative due to existing adoption.

Go 2 will never happen, they will keep incrementing 1.x until end of current computing model.

Re: Excessive nil pointer checks in Go

#37
post #21
post #9

This is the mess a language lands on when it conflates optionality (a semantic concept) with references/pointers (purely a machine concept). In Go, the requirement " need (non-optional) a reference to an object" is simply not expressible. This is a solved problem in other languages, for example `&T` vs. `Option ` in Rust.

It's really difficult to view Go as a serious language when fundamental design decisions such as this one have seemingly been glossed over. It's in a precarious spot, on the one hand cushioning the C it wants to resemble, but on the other hand not yielding any capable tools or abstractions which could otherwise be unlocked via the safe architecture. Go developers seem uninterested in language design.

It's not that it has been glossed over, or was a mistake. It's a tradeoff in favor of simplicity (and compiler / tooling speed).

It is difficult to view Go as a serious language because it fails to acknowledge these decisions, repeatedly. You can't really trust the language in that sense.

Re: Excessive nil pointer checks in Go

#40
> You may attempt to address this by pushing the problem up one layer. You now check for nil and return an error to flag the nil dependency as an invalid state.

> It’s better, but it’s still not correct. Why not? Because we still allowed the invalid state to enter our system. A nil pointer is still being passed to our function, which puts the burden of deciding whether to trust the input on code that should have received a valid value in the first place.

> The constructor is not where the error happened. The error happens at the initialization site:

> Once initialization fails, we should handle that error immediately. We should not continue with a nil pointer and force the next, deeper layer to rediscover the outcome. Doing so also removes the need for the rate limiter constructor to return an error in the first place!

But... surely it'd be better to leave this guard rail of a nil check in the rate limiter constructor, to quickly and accurately detect regressions in the very possible future where you reshuffle the code that constructs your objects?

> The check belongs at the boundary

Wait... is the author operating under an assumption that I control (almost) the whole of my codebase, so there is no need to have the boundaries inside of it?

Post reply on HN