Hacker News new | ask | show | jobs
by cpuguy83 3225 days ago
Errors can be anything. It's just an interface.
2 comments

Except you don't get to control the specific error type returned by packages you import. So sure, you could get stack traces for your code, but not for your dependencies.

It infuriates me when go proponents try and sweep bad language decisions under the rug with half-fixes.

https://twitter.com/codebeeCA/status/885302657178587136

To be fair, the Go authors have always strongly promoted that you fork and maintain your dependencies. That may be a bad operational decision (outside of Google), but is technically unrelated to the language itself.

Mind you, if third party code needs debugging, you're going to have to fork it in order to apply your fixes in a timely manner anyway. Perhaps their stance is not as crazy as it may originally seem.

And with my professional experience, sometimes maintaining a program over a decade, I have to agree. When you are using an external library, you have to at least have a copy of the version you are using. Repositories might go away without a warning. Also, you want to go to a new version only after some review. Ideally, you don't have any local modifications - if you patch libraries, you should donate the changes back. But then, it happened that patches were rejected. In the end you are going to need a local copy/branch for several reasons.
> Also, you want to go to a new version only after some review

Happened here recently - modules used in the core build aren't versioned which means when someone external updated a module with an incompatible change, the build broke.

Moral: Never build direct from CPAN / GOPAN / CCAN / WHATEVSPAN without pinned versions.

Can you point me to a quote where Go authors have encouraged people to fork a third party library in order to insert better error handling code?

I don't want to insult anyone, but this seems like an utterly insane software engineering practice to me. It means you can't just update to the next version of that library any longer. You're taking it upon yourself to review and patch every single new version of that library. Manually.

See: Any discussion related to go get and its design motivations.

Even vendoring, which was added to the tooling later, is built on the idea of keeping your own fork. It just simplifies the forking process for people who do not work like Google does, where each fork is shared company-wide.

GP is right: this is insane.

Not only are people here suggesting that you fork your dependencies to add stack traces to errors, which is a problem no other modern language seems to have, but it's also going to be a security disaster when some common package is found to have a vulnerability and ten percent of projects ever bother to update it.

I feel like I've entered some sort of bizarro world where everyone has forgotten that programming doesn't have to suck and pretends that none of this is a problem.

I love programming in Go but the thought of forking and maintaining every single library I might use in one of my projects makes me also feel we've entered a new, bizarre, and terrifying world. This is literally one step away from "write your own OS and compiler, it's the only way to be sure you get the exact behavior you want".
I know the debate. It's a debate about versioning, not about maintaining your own fork in order to insert your own error handling philosophy into third party libraries.
They have always maintained that Google does modify the packages and maintains any necessary merging and maintenance of the package. It is not just about versioning. This is why they maintain their own repository of third-party libraries in the first place, and why the tooling is designed to support their forking methodology.

Again, this may be a poor operational choice for those outside of Google, but they have also been quite clear that Go is built for the problems that Google has. If your problems are different, it may not be the right tool for the job. A hammer doesn't have to be able to cut wood. There is no harm in choosing a saw instead.

It's worth noting that nobody is saying you can't fix that problem in your dependencies.

When you rely on dependencies you have to expect that not all of them will carry the same quality of code which you create yourself.

it infuriates me when third-party stuff in other languages throws exceptions and you end up needing to check everything anyway.

exceptions are a curse.

> it infuriates me when third-party stuff in other languages throws exceptions and you end up needing to check everything anyway. exceptions are a curse.

Anything can panic in Go. Go gives absolutely no guarantee something cannot panic. Errors as values are just a convention. So exceptions are a curse but Go has an inferior exception system, panics, but they are still exceptions.

The solution is checked exceptions.

It's fine if you think exceptions are bad, but throwing out the ability to easily determine where an error occurred (and might I add, from having seen go code in practice, having humans just become meat-based manual exception-handlers bubbling errors up to the top) is throwing the baby and the bathtub and the entire bathroom out with the bath water.
Errors are part of the third-party stuff's API. Don't be surprised if you have to handle them.
Which to be clear, is a language design mistake. Go would be a much more productive and friendly language if errors would just have stack traces on them when they're created. There's no reason to have the poor developer adding dozens of debug prints all over his (and sometimes third-party) code manually into every place that could have returned the error just to try and discern where it comes from. Or grepping for strings in the error message, or throwing darts at printouts of the source. That's just a massive step backwards from what we've had since the 80s and 90s. I know Go prides itself on being simple, but really the errors are too simple and we're all worse off because of it.
The problem is that Go errors are just a convention, they are not a feature of Go. It's just an interface, it could have been called FOO it wouldn't have made a difference. Go has exceptions, they are called "panic" by they are inferior to Java in the way they are handled.
I know they're just a convention, but that was a mistake. It should have had more first-class language support so that they have stacktraces at least.

I'm seriously beginning to think that even with the limitations, panic is a better error handling mechanism for all exceptional error cases. At least it has stacktraces and doesn't clutter the code with error boilerplate. I don't think I'd be able to convince anyone of that on a real project though, I'd have to try it on a personal project.