8 ms·
> Nil panics are found to be an especially pervasive form of runtime errors in Go programs. Uber’s Go monorepo is no exception to this, and has witnessed severa
by insanitybit 3y ago
> Nil panics are found to be an especially pervasive form of runtime errors in Go programs. Uber’s Go monorepo is no exception to this, and has witnessed several runtime errors in production because of nil panics, with effects ranging from incorrect program behavior to app outages, affecting Uber customers.
Insane that Go had decades of programming mistakes to learn from but it chose this path.
Anyway, at least Uber is out there putting out solid bandaids. Their equivalent for Java is definitely a must-have for any project.
- deleted 3y ago[deleted]
- MichaelNolan 3y agoThe go version NilAway isn’t as good as the java version NullAway yet. But the team working on it is very responsive and eager to improve. For java projects I think NullAway has gotten so good that it really takes the steam out of the Kotlin proponents. Hopefully NilAway will get there too.
- tuetuopay 3y ago> Insane that Go had decades of programming mistakes to learn from but it chose this path. Yup, every time I write some Go I feel like it's been made in a vaccum, ignoring decades of programming language. null/nil is a solved problem by languages with sum types like haskell and rust, or with quasi-sums like zig. It always feels like a regression when switching from rust to go. Kudos to Uber for the tool, it looks amazing!
- IshKebab 3y agoDart made the same nullable mistake but actually managed to fix it, which is quite impressive. Go is just obstinately living in the 90s. I guess that's not really a surprise. It's pretty much C but with great tooling.
- yoyojojofosho 3y agoDart has a great write up on how they fixed the null problem by adding non-nullable types: https://dart.dev/null-safety/understanding-null-safety https://dart.dev/null-safety/understanding-null-safety
- masklinn 3y agoSeveral language have "fixed the null problem" after the fact, though usually as an opt-in e.g. typescript, C#. The problem with Go (for this specific issue, there are lots of problems with Go) is that they have wedded themselves extremely strongly to zero-defaulting, it's absolutely ubiquitous and considered a virtue. But without null you can't 0-init a pointer, so it's incompatible with null-safety. I think C# pretty much left the idea of everything having a default behind when they decided to fix nulls. Though obviously the better alternative is to have opt-in defaulting instead.
- pcwalton 3y agoThis is a good point. Null pointers are the billion-dollar mistake, but the real billion-dollar mistake is having "zero values" in your language. In addition to the problems with null pointers, zero values make loose constructor semantics like C# and Java tempting, where objects can exist in a not-fully-initialized state, leading to lots of room for confusing bugs. Without zero values to fall back on as a crutch, the language design is forced to tighten that up so that objects are either completely initialized or completely uninitialized, like in ML or Rust†, which is a much cleaner semantics. (The funny thing is, Go has the tools to get rid of zero values by virtue of not having constructors, but it chose not to use them for that!) † Strictly speaking, objects can be partially initialized and partially uninitialized in Rust, but this is harmless as the borrow checker statically ensures that uninitialized fields of objects are never accessed.
- masklinn 3y agoYeah technically you can always default init fields to None, but then you have to type everything as an Option and the ergonomics are so bad you're really incentivised not to do that. In that case you bundle that in a transient structure (a builder) and you get rid of it afterwards.
- usrbinbash 3y ago> ignoring decades of programming language True, and because of this, the language can be learned over a weekend or during onboarding, new hires can rapidly digest codebases and be productive for the company, code is straightforward and easy to read, libraries can be quickly forked and adapted to suit project needs, and working in large teams on the same project is a lot easier than in many other languages, the compiler is blazing fast, and it's concurrency model is probably the most convenient I have ever seen. Or to put this in less words: Go trades "being-modern" for amazing productivity. > It always feels like a regression when switching from rust to go. It really does, and that's what I love about Go. Don't get me wrong I like Rust. I like what it tries to do. But I also love the simplicity, and sheer productiveness of Go. If I have to deal with the odd nil-based error here and there, I consider that a small price to pay. And judging by the absolute success Go has (measured by contributions to Github), many many many many many developers agree with me on this.
- insanitybit 3y ago> And judging by the absolute success Go has (measured by contributions to Github), many many many many many developers agree with me on this. Yeah, I truly hate this field
- nicoburns 3y agoIt could have done both though. It could have explicitly nullable types like Kotlin/C#. Or sum types like zig/rust/Swift. That wouldn’t make the language more complex to learn.
- marsavar 3y agoWhile this is a great piece of engineering, and will certainly deliver a huge amount of value to any project, the fact that a whole new tool had to be built (and will have to be maintained) to address serious, fundamental shortcomings in the language is really quite sad.
- foldr 3y agoIt's worth bearing in mind that some of these runtime panics would have happened anyway even if the code had been implemented in (e.g.) Rust. Ugly real world code tends to make quite frequent use of unwrap() or equivalents. For example: https://github.com/search?q=repo%3Arust-lang%2Frust+.unwrap%28%29&type=code https://github.com/search?q=repo%3Arust-lang%2Frust+.unwrap%...
- insanitybit 3y agoYou can `grep unwrap` for Rust, you need an entire SAT solver for Go.
- tgv 3y agoWhat do you think the borrow checker is?
- insanitybit 3y agoA completely unrelated construct?
- foldr 3y agoThat's almost literally what I just did, but what use is it? No-one is really going to go through all those unwrap calls and check them.
- insanitybit 3y agoBut... they could. And also, they do? It's not uncommon. All of those could be checked or irrelevant, I have no idea.
- mariopt 3y agoRust is a lot better in this aspect, but this is a symptom of not having proper code review and standards. Do not forget that in some scenarios using unwrap is totally fine if a panic is acceptable. The same could be said for javascript: How many time have we not wrapped JSON.parse inside a try catch? More than we would like to admit. Really appreciate Rust “forces” you to handles all execution paths.
- skybrian 3y agoI don’t see this as a band-aid. It’s doing proper type checking (static analysis) and that seems quite promising? Getting good type errors without requiring type annotations seems like a win over languages that are annotation-heavy. Normally I’d be skeptical about relying on type inference too much over explicit type declarations, but maybe it’s okay for this problem? This is speculative, but I could see this becoming another win for the Go approach of putting off problems that aren’t urgent. Sort of like having third-party module systems for so many years, and then a really good one. Or like generics.
- insanitybit 3y agoI guess you could call it a bandage? The point wasn't to bad-mouth it or undersell it - bandaids are awesome. The point is that we need some external thing to patch holes in the underlying system.
- bb88 3y agoAgree, this is dumb. This should be a part of the compiler if the language def can't simplify this for the user.