5 ms·
Pointers are "nullable types", but if you're seeing that a lot, it generally indicates an architectural problem.
by 65a 3y ago
Pointers are "nullable types", but if you're seeing that a lot, it generally indicates an architectural problem.
- segfaltnh 3y agoAgree with this. While I too wish that Go had better ways of handling this, there are patterns and guidelines to follow that should prevent this in practice. - Use factory functions for struct initialization where members are pointers. - Use errcheck and friends to ensure errors are not ignored. - Never dereference the left hand return value if the right hand is an error.
- itake 3y ago+1. I only run into this issue when I don't follow the proper patterns our of laziness.
- neonsunset 3y agoI believe the problem is if this happens to be an issue in a dependency, which you can have little recourse to. Let’s wait another decade or so and maybe the Go authors will catch on lessons learned by C# (and similar languages) long ago by introducing nullable reference types and all kinds of static analysis to help you not shoot yourself in the foot.
- groestl 3y ago> - Use errcheck and friends to ensure errors are not ignored. - Never dereference the left hand return value if the right hand is an error. This itself is a very concise argument for exceptions. Automatically checks errors are not ignored, and don't allow access to the left hand return value.
- ncruces 3y agoBubbling up errors is not handing them. Making bubbling up even easier because people find this too verbose is the original mistake: if err != nil { return err } I find it verbose too. But if the alternative is to design something that allows you to ignore it 99%, and then put a huge syntactic penalty into doing anything other than bubbling up, then people will just bubble up 99.95% of the time, and complain about the other 0.05. I'm all for ensuring errors are not silently ignored. That's Go's mistake. Exceptions are not the answer.
- segfaltnh 3y agoI strongly agree. In principle, exceptions are a streamlined version of tossing err up the stack without any embellishment. In practice, I put cookies away in the cabinet so that I don't eat them. Humans write code, and our behaviors change in response to our surroundings. I think a lot more about failure cases in Go than Ruby. Maybe you're not like that, but you're the exception that proves the rule!
- groestl 3y ago> In principle, exceptions are a streamlined version of tossing err up the stack without any embellishment. This is exactly what I meant. It's "handling", when viewing the consuming function as failing system. It's not "handling" when viewing the application as failing system.
- chuckadams 3y agoChecking for exceptional conditions after every operation sounds an awful lot to me like checked exceptions with extra steps.
- ncruces 3y agoYes. The point is the extra steps mean that the delta between “just bubbling up” and “doing something about it” is smaller, which increases the chance that you'll consider “doing something about it.” If “bubbling up” is infinitely easier than handling it, you'll postpone handling it as much as you can.
- chuckadams 3y agoYet most Go code in the wild does nothing but bubble up the error. Three out of every four lines of code dedicated to doing nothing more than that. If only there were syntax sugar doing so automatically, maybe even a compiler mechanism for forcing you to declare those that you do push up to the caller in such fashion... I don't even particularly like exceptions either, I just like having to implement them by hand even less. Meanwhile, all the Smug Lisp Weenies™ are chuckling and mumbling something about "restarts". What really kills me is that Go has a structured exception mechanism with panic/recover/defer, and it's actually better than try/catch/finally at that. It just doesn't seem to have caught on as the standard exception handling idiom.
- Mawr 3y agoThere's some tooling out there: "NilAway: Practical nil panic detection for Go" https://news.ycombinator.com/item?id=38300425 https://news.ycombinator.com/item?id=38300425
- segfaltnh 3y agoHave you had practical success with this? It seems every discussion about Go error handling someone posts this but in all our projects it's riddled with false positives. I'm not convinced it's practically useful, though it is academically interesting.
- Mawr 3y agoNo, just a few false positives. I don't have issues with null in my projects in the first place though.
- preommr 3y agoThis is why one of the often quoted benefits of golang being it's small languag design is so annoying - it doesn't help if there's then a bunch of other implicit rules that have to be remembered that aren't made explicit through the langauge. It's actually much worse, because these lessons then have to be learned in some other long-winded fashion like official blog posts, additional guidelines, or even worse, random posts online and self-learning through mistakes.
- segfaltnh 3y agoI can't think of a language that has less of these sorts of things you have to internalize than Go. Sure, they're annoying, but so many other languages have even more rough edges. Maybe you could argue Rust does because it refuses to compile a ton of invalid cases, but I consider the time it takes me to write usable code (whether that's compiling or passing some runtime tests) an important metric.
- TheDong 3y agoSure, pointers are nullable types, but they also are necessary for mutability, so you're forced to use them for non-nullable things too. You'll notice the go stdlib uses pointers for things which absolutely should not be nullable types, like '(*big.Int).Add(*big.Int, *big.Int)', or 'time.NewTimer() *time.Timer'. 'time.NewTimer' will never return a nil. 'big.Int.Add(x, y)' requires all of those things to be non-nil. However, those are all pointers for unrelated reasons, like mutability, and so clearly pointers are not _just_ "nullable types".