Live data from Hacker News

Excessive nil pointer checks in Go

konradreiche.com

21–30 of 116 posts

Re: Excessive nil pointer checks in Go

#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.

Re: Excessive nil pointer checks in Go

#22
post #14
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.

In C++, that distinction supposedly exists. References should never be null, while pointers can be. But there's no enforcement. int& ref = *ptr; ought to generate a panic for a null pointer. But it doesn't. They were so close to getting it right.

Im not entirely sure this helps with your point but;

The contract is that the reference is still non-null, and that the error is dereferencing the pointer. There’s two big problems with defining the behaviour of the deterrence - 0 is a valid memory address on some (ancient) platforms so for better or worse the behaviour is platform dependent.

The other is that there’s many other ways to have absolute garbage in a pointer that aren’t null.

    int& foo() { 
        int local = 42;
        return local;
    }
Now, a compiler catches this case, but the point is that null isn’t the only invalid state that needs to be checked. Adding a compiler overhead of checking each pointer to every single pointer dereference wouldn’t work.

Modern codebases ran with static analysis tools will catch these errors (honestly even valgrind will find most if not all of these).

Re: Excessive nil pointer checks in Go

#23
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.

What the article said applies to Rust ref vs ref-option too.

Not really. It's possible to write this mistake but it's pretty obviously a bad idea, I've never seen someone do this and need correcting.

Edited to expand: Sometimes it feels reasonable to have a construction function which returns Option rather than Goose because you might be OK with getting back None, for example if you want to make a NonZeroU8 the function to do that will of course give you back Option because you might give it a zero and that's er... not nonzero. But I've never seen people go oh, OK, I guess i'll scatter all my checks throughout the rest of my software and just pass Option everywhere even though I need a NonZeroU8. Rust's shape encourages them to check once during creation like this article suggests.

Re: Excessive nil pointer checks in Go

#24
post #14
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.

In C++, that distinction supposedly exists. References should never be null, while pointers can be. But there's no enforcement. int& ref = *ptr; ought to generate a panic for a null pointer. But it doesn't. They were so close to getting it right.

[deleted]

Re: Excessive nil pointer checks in Go

#25

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 mistakes are just no-go.

So close indeed.

They need Go 2 with *T and ?*T - that would be nice language to use.

Re: Excessive nil pointer checks in Go

#26
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 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.

Re: Excessive nil pointer checks in Go

#27
post #20
post #8

Also known as contract programming vs. defensive programming. This argument is very old, is not specific to golang, and I have found myself on both sides at different points in my carreer.

Fortunately we have type systems to encode many contracts at compile time, including stuff like optionality. Certainly no modern language would still repeat Hoare’s "billion dollar mistake"? Right? …Oh.

It's so bad that here we are in the 21st century and there are even still people who insist it wasn't a mistake e.g.: https://www.gingerbill.org/article/2026/01/02/was-it-really-...

Re: Excessive nil pointer checks in Go

#28
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 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.

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

Re: Excessive nil pointer checks in Go

#29

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.

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

you still need to unpack that option somewhere.

Re: Excessive nil pointer checks in Go

#30
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 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.

Post reply on HN