Live data from Hacker News

NilAway: Practical nil panic detection for Go

uber.com

111–120 of 262 posts

Re: NilAway: Practical nil panic detection for Go

#111

> 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…

Agree, this is dumb. This should be a part of the compiler if the language def can't simplify this for the user.

Re: NilAway: Practical nil panic detection for Go

#112
post #100

Earlier quoted context omitted.

There are several language design problems solved in the 20th century that Go designers decided to ignore, because they require PhD level skills to master, apparently. Hence why the language is full of gotchas like these. Had it not been for Docker and Kubernetes success, and most likely it wouldn't have gotten thus far.

speaking from personal experience, i selected go for a project because it is high perf, automatically uses all cores w/ goroutines, and is type checked

> type checked

Kinda...

Re: NilAway: Practical nil panic detection for Go

#113
post #93
post #78

It amazes me that in 2023 this is not a solved problem by design of the language. Why go doesn’t adapt the “optional” notion of other languages so that if you have a variable you either know it is not null or know that you must check for nullness. The technology exists

There's much I don't love about Rust, but I feel golang could steal the ? operator and keep the spirit of go. Effectively, instead of result, err := doSomething() if err != nil { return nil, err } you'd get the same control flow with result := doSomething()?

Try (the current incarnation of the ? operator) is actually a very clever trait which does rather more than that.

Types for which Try is implemented can Try::branch() to get a ControlFlow, a sum type representing the answer to the question "Stop now or keep going?". In the use you're thinking of where we're using ? on a Result, if we're Err we should stop now, returning the error, whereas if we're OK we should keep going.

And that's why this works in Rust (today), when you write doSomething()? the Try::branch() is executed for your Result and resolves into a Break or a Continue which is used to decide to return immediately with an error or continue.

But this is also exactly the right shape for other types in situations where failure has the opposite expectation, and we should keep going if we failed, hoping to succeed later, but stop early if we have a good answer now.

Re: NilAway: Practical nil panic detection for Go

#114
post #110
post #109

Earlier quoted context omitted.

And now they're stuck, since they doubled down on not making any language changes for the 2.0 release. They made the language easier and quicker to write a compiler, but harder to write programs in, and it doesn't look like that will change in Go 2.0.

At least many CNCF projects are now adopting Rust, Java, C# and even to a lesser extent C++.

There's nothing better than a panic in production caused by a third party library.

Re: NilAway: Practical nil panic detection for Go

#115

Is there any movement in the language spec to address this in the future with Nil types or something?

I really love Golang and how it focused on making the job of the reader easy. But with today’s modern programming language the existence of null pointer dereference bugs doesn’t really make sense anymore. I don’t think I would recommend anyone to start a project in Golang today.

Maybe we’ll get a Golang 3 with sum types…

Re: NilAway: Practical nil panic detection for Go

#116
post #89

90 million lines of code to .. call a cab? Genuinely curious what's so much of business logic is for.

I was working on a Grab competitor, you would be surprised about the number of subsystems running there.

There are entire teams that are working on just internal services that connect some internal tools together.

There was also very little effectivity and efficiency in the era of cheap capital so there were tons of talent wasted on nonsense. Uber built their own slack for a while!! (before just going to mattermost)

People always ask who actually makes money on Uber... I think it's not the cab drivers, not the investors, who makes money is the programmers. It's a transfer of money from Saudis to programmers.

Well it was, anyway.

Re: NilAway: Practical nil panic detection for Go

#117
post #56

Earlier quoted context omitted.

This is the core of the problem. Of course you can learn the language in a weekend, but you're bound to make the same mistakes developers have been doing for decades. This may be ok, as you say, if you allow errors here and there because you are fine dealing with those problems. But at the other end, it may be a user that is affected by the error. Which may be ok as well, but why should it be? We lament the quality o…

Go is just making a certain set of tradeoffs. If you try to fix all the "mistakes developers have been doing for decades", you get Rust. And considering that Rust is already Rust, there is not much point in trying to make Go another Rust. The line has to be drawn somewhere. I think everyone has certain things they'd put on the other side of that line, and strict nils are probably at the top of the list for many, but…

I don't think anyone is suggesting that Go should be like Rust. It's too late for that. We're suggesting that people should just use Rust (or Haskell, or F#, or any other robust functional programming language) instead.

Re: NilAway: Practical nil panic detection for Go

#118
post #64

Earlier quoted context omitted.

> True, and because of this... This is a false dichotomy. One does not imply the other. Go is also not a simple language. It is deceptively difficult with _many_ footguns that could have easily been avoided had it not ignored decades of basic programming language design. Many things also aren't straightforward or intuitive. For instance, this great list of issues for beginners: http://golang50shad.es/

I'm sorry but nearly all of them are along the lines of "I came from language X and in X we did it this way, but Go's syntax is different". That's not a footgun. You know what's a footgun? Uncaught exceptions popping up in places far away from where they were created at which point you have very little context to deal with it robustly. Use after frees. FactoryFactoryFactories.

I don’t have too much an opinion on either side here, but as a developer who works full time in Go (and has for >6 years) all these things exist in Go.

Uncaught exceptions -> panics, like what this nil catcher is aiming to solve

Places far away -> easy goroutine creation with no origin tracking makes errors appear sometimes very far away from source

Use after free -> close after close

FactoryFactoryFactories -> loads of BuilderFunc.WithSomething

Lots of other pains I could add that are genuinely novel to Go also, but funny that for everything you mentioned my head went “yep, just called X”

Re: NilAway: Practical nil panic detection for Go

#119
post #114
post #110

Earlier quoted context omitted.

At least many CNCF projects are now adopting Rust, Java, C# and even to a lesser extent C++.

There's nothing better than a panic in production caused by a third party library.

This whole thread is about the money Über has spent to work around panics in Go.

Re: NilAway: Practical nil panic detection for Go

#120
post #71

Earlier quoted context omitted.

With generics, can you not make a NonNil struct in Go, where the contents of the struct are only a *T that has been checked at construction time to not be nil, and doesn't expose its inner pointer mutably to the public? I would think that would get the job done, but I also haven't really done much Go since prior to generics being introduced Otherwise, since pointers are frequently used to represent optional parameter…

Every type in Go has a zero value. The zero value for pointers is nil. So you can't do it with regular pointers, because users can always create an instance of the zero value.

This is one of those things which feels like just a small trade off against convenience for the language design, but then in practice it's a big headache you're stuck with in real systems.

It's basically mandating Rust's Default trait or the C++ default (no argument) constructor. In some places you can live with a Default but you wish there wasn't one. Default Gender = Male is... not great, but we can live with it, some natural languages work like this, and there are problems but they're not insurmountable. Default Date of Birth is... 1 January 1970 ? 1 January 1900? 0AD ? Also not a good idea but if you insist.

But in other places there just is no sane Default. So you're forced to create a dummy state, recapitulating the NULL problem but for a brand new type. Default file descriptor? No. OK, here's a "file descriptor" that's in a permanent error state, is that OK? All of my code will need to special case this, what a disaster.

Post reply on HN