Live data from Hacker News

Excessive nil pointer checks in Go

konradreiche.com

51–60 of 116 posts

Re: Excessive nil pointer checks in Go

#51
post #50

Earlier quoted context omitted.

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

I think the author can propagate RateLimiter instead of *RateLimiter, making it exactly the same

No, because RateLimiter is then copied on passing it around (pass by value).

That is problematic for two reasons: it might be a large type, so copying might be expensive. Second, more likely, it might violate invariants in your domain. For a rate limiter, this might mean accidentally copying around some internal state like a mutex, which then exists n times instead of 1 time, which can represent a problem (e.g. if you want to internally limit whole-app concurrency toward Redis).

Re: Excessive nil pointer checks in Go

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

There's nothing particularly special about null pointers: you can also have an invalid non-null pointer, e.g. through pointer arithmetic.

When you write `int& ref = *ptr;` you are dereferencing the pointer with `*ptr` therefore you have promised that it's valid. The compiler doesn't need to do anything to validate ptr because it already has your assurance.

It's really no different than if you were to write `printf("%d", *ptr);`. It's only a little weird because in `ref = *ptr;` the compiler doesn't actually emit any instruction for the dereference, but that doesn't mean that the assurance you gave doesn't exist.

It would indeed be problematic were it to be `int& ref = ptr;` without the dereference but it's not.

Re: Excessive nil pointer checks in Go

#53
post #50

Earlier quoted context omitted.

I think the author can propagate RateLimiter instead of *RateLimiter, making it exactly the same

No, because RateLimiter is then copied on passing it around (pass by value). That is problematic for two reasons: it might be a large type, so copying might be expensive. Second, more likely, it might violate invariants in your domain. For a rate limiter, this might mean accidentally copying around some internal state like a mutex, which then exists n times instead of 1 time, which can represent a problem (e.g. if yo…

You can see the code

Clearly is not large. Second the child object is a pointer so does not violate anything

And if if if... I am sure we can look for new constraints in any language

Re: Excessive nil pointer checks in Go

#55

I'd really really wished, with all of the history behind us, that golang would have learned from it. All they had to do was make pointers nonnull by default. Immutable-by-default would also have been nice. A man can dream...

It is tragic. Another repetition of Hoare's Billion Dollar Mistake, exactly where it should not have been made, long after the consequences were well understood, and also previously repeated at the time Go was conceived.

There really isn't an excuse, and it isn't possible to hate null/nil/undefined/etc. enough.

Re: Excessive nil pointer checks in Go

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

This is the most boring argument in computer science. It's like arguing about whether a language should have "goto" or not. There is no new ground to tread here. Most mainstream languages have null references. An entire cinematic universe of languages have been built from the premise that you should not have null references. This is a fundamental rift in programming language theory, and the very best you can do on HN, at least on stories where that rift is not the main point of the article, is to restate it poorly.

Seriously, Tony Hoare dropped the mic on these arguments back in 1965. You have to move forward in these discussions on the premise that everybody already gets this very basic, very old PLT argument.

Just like if you had somehow managed to find a way to do a spaces versus tabs complaint in a story about (I don't know) Typescript, you will reliably generate sprawling threads by bringing this stuff up on any thread about a language with null references. It's easy for everybody to have an opinion here! Everybody knows the issue! Not everybody agrees! But you aren't doing any good for the thread itself; you're just jamming it.

Re: Excessive nil pointer checks in Go

#57

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…

> Don't use pointers at all, always allocate structs on the stack

Unless one makes the rookie mistake of passing these structs to pkg log (which box to any/interface{}) instead of slog [0]... then they escape to heap. If a project relies on avoiding heap allocs, prudent to 'go build -gcflags="-m"' on every check-in, and review the diff from that too.

[0] https://go.dev/blog/slog

Re: Excessive nil pointer checks in Go

#58
post #56
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.

This is the most boring argument in computer science. It's like arguing about whether a language should have "goto" or not. There is no new ground to tread here. Most mainstream languages have null references. An entire cinematic universe of languages have been built from the premise that you should not have null references. This is a fundamental rift in programming language theory, and the very best you can do on HN…

> Seriously, Tony Hoare dropped the mic on these arguments back in 1965. You have to move forward in these discussions on the premise that everybody already gets this very basic, very old PLT argument.

cf. https://news.ycombinator.com/item?id=12427069

Re: Excessive nil pointer checks in Go

#59

This is good advice for humans: they can quantify to decide "too many nil checks" or not. But it's not good for agentic coding, which we're entering the age of. Although agents are the worst they'll ever be right now, they're never going to be great at quantifying too many nil checks. I think we'll have to get used to far more nil checks than even bad programmers put in. But that doesn't matter to agents, they've got…

they're never going to be great at quantifying too many nil checks

Why not?

Re: Excessive nil pointer checks in Go

#60

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…

> Don't use pointers at all, always allocate structs on the stack Unless one makes the rookie mistake of passing these structs to pkg log (which box to any/interface{}) instead of slog [0]... then they escape to heap. If a project relies on avoiding heap allocs, prudent to 'go build -gcflags="-m"' on every check-in, and review the diff from that too. [0] https://go.dev/blog/slog

Good to know, but wouldn't that be something that pops up when profiling?
Post reply on HN