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.
Excessive nil pointer checks in Go
11–20 of 116 posts
Re: Excessive nil pointer checks in Go
#12This 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.
Re: Excessive nil pointer checks in Go
#13Delegate all `nil` and bad input checks to a validation framework and use it in all your constructor functions.
Re: Excessive nil pointer checks in Go
#14This 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.
int& ref = *ptr;
ought to generate a panic for a null pointer. But it doesn't. They were so close to getting it right.Re: Excessive nil pointer checks in Go
#15There 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 will understand (we did this at some point and it was a huge improvement).
Don't use pointers at all, always allocate structs on the stack, pass them by value.
You pay the copy price, even with large structs, and that's fine. When there are exceptions, be very explicit about the reason: performance must be critical,not just an optimization.
Don't ever check interfaces for nil, if you need some sort of optional parameter, make a separate function and make it pass an valid object for that interface that's a null object.
These two did improve things substantially
Re: Excessive nil pointer checks in Go
#16“Nil Check on a Dependency in the Constructor”, at least in the way it is described in article’s example.
The _parameter_ check in the constructor is the standard practice of testing on perimeter/blundaries. You test your parameters on the public methods (that constructor obviously is), and assume valid state in private methods. And even there I can accept practice of debug build assertions (DCHECK/TCHECK in Google c++ terminology ).
Re: Excessive nil pointer checks in Go
#17This 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.
Re: Excessive nil pointer checks in Go
#18What about wrapping nil in a Maybe or Option type?
In this case, the missing piece in Go is the NonNullable hint. That would make it clear that null checks aren't needed, enforceable by the type system, and lintable. Option types just forces you to do the check, but doesn't remove the need for it. Now that we have generic types, a NonNullable intrinsic type seems doable...
Personally I do experiment with these things as it makes code more readable, it just seems adoption for generics and what you can do with them is still quite low in the broader community. That said I do not deal with null pointer exceptions much at all, and when I do it's often relatively simply to spot and fix, so for me it's not a large issue.
Re: Excessive nil pointer checks in Go
#19This 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.
The philosophy of C++ is to not introduce unnecessary overhead, and to trust the programmer. This design choice is prevalent throughout the language. They were never going to make an exception, especially for something as prevalently used as references.
There are countless examples of this "no unnecessary overhead and/or trust the programmer" choice:
- primitive types and standard containers are not thread safe - it's up to the programmer to know this and use them accordingly.
- std::unique_ptr lets you grab the underlying raw pointer, in which case it's no longer a "unique_ptr". But there are cases in which it's useful to do this (e.g. interfacing with C code), so they let you do it, and trust that you do it in a safe way. They could have made unique_ptr not support this, but then it would be less useful (or force you into copying data unnecessarily to call an API that requires a raw pointer).
> But there's no enforcement.
There's no strict enforcement, but it is undefined behaviour, so compilers can randomly choose to act as if it's enforced and simply crash your program or make it act weirdly.
Re: Excessive nil pointer checks in Go
#20Also 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.