Live data from Hacker News

Gopher Wrangling: Effective error handling in Go

stephenn.com

141–150 of 310 posts

Re: Gopher Wrangling: Effective error handling in Go

#141
post #6

For a language where coroutines are such a first-class citizen, I wish there was a more idiomatic way of returning and handling async errors in Go. I know it's all over the docs, but using a channel has always felt so "wrong." The errgroup lib tries to fix this, but it's still not as flexible as using a channel (for example, if you want to store or log all routine errors).

As far as I understand Go, passing back results via channels is the idiomatic approach for this. But the provided example is wrong - it is synchronous, as it awaits the computations to finish; and it is broken, because if either `refresh` call panics the caller will hang indefinitely. So it needs some extra defers and maybe a sync.WaitGroup Also, example 5 is also somewhat not good, because it uses `if err == context…

> As far as I understand Go, passing back results via channels is the idiomatic approach for this.

It's definitely the canonical way, but communicating errors via channels feels very.. weird, for the lack of a better word (hence why I don't find it idiomatic).

Re: Gopher Wrangling: Effective error handling in Go

#142
post #136
post #91

Could someone explain why is Go so hyped? In my personal opinion it is just not a good language, and I think many judge it based on some false basis that it is somehow “close to the hardware” because it produces a binary. Like, the amount of time it is put next to Rust when the two have almost nothing in common.. It is very verbose, yet Java is the one that is called that, often by Gophers, which is much more concise…

In my personal opinion it's a great language to solve problems _I_ have to deal with in course of my work. Can I solve them with Java? Sure. Difference is go does not have the complexity you can find in Java and quite opinionated. So you don't have to spend as much time working with the language inself and can focus on getting the job done. Go is not as expressive and some other languages and does not have the same a…

Could you elaborate on exactly what complexity in Java you're referring to?

By having an overly simplistic language, you end up pushing more complexity onto the programmer and into the code base. There is no free lunch.

I find it much more sane to solve and express code in Java. You get terser, more to the point code that reflects the underlying logic more clearly, compared to having to read many lines or pages to understand what's going on.

Re: Gopher Wrangling: Effective error handling in Go

#143
post #91

Could someone explain why is Go so hyped? In my personal opinion it is just not a good language, and I think many judge it based on some false basis that it is somehow “close to the hardware” because it produces a binary. Like, the amount of time it is put next to Rust when the two have almost nothing in common.. It is very verbose, yet Java is the one that is called that, often by Gophers, which is much more concise…

It has:

* Relatively simple syntax.

* "Good enough" expressivity-- nothing that's considered "missing" has been a true blocker for most projects.

* An easily accessible concurrency primitive, with the bonus that the runtime can choose to execute goroutines in parallel (when able)-- this comes with no required function coloring or split in a code base.

* A well opinionated environment packaged with the compiler: default formatter, default method for fetching remote deps, default documentation generator, default race detector, default profiler, default testing system.

* Decent portability-- can cross compile relatively easily from one platform to another, doesn't require a larger runtime pre-installed on the foreign host.

* "Batteries included" standard library.

* Inertia-- enough of an active community to pull what you need from the Internet, whether it's guides or code.

* A "good enough" type system to catch some errors before they become runtime errors.

* A "good enough" abstraction for operating on data with: structs, interfaces, and methods. With composition being preferred over inheritance, and embedding bringing handy sugar.

No language is perfect, everyone has an opinion, but for many people this is "close enough" to what they prefer to work with.

Gophers may just be a bit more vocal about it.

Re: Gopher Wrangling: Effective error handling in Go

#144
post #116

Go's error handling is a horrible mess: 1. It's easy to ignore returned errors without any compiler warnings. You have to rely on third party tools such as golangci-lint to report missing error handling. 2. Errors don't carry stack traces with them, you have to rely on third party libraries or custom errors to get that functionality and you will only get it for your own code, not in other libraries you are using. 3.…

>3. It's unclear who should add context to error messages is it the caller or callee? Usually it gets skipped, leading to useless error messages

Why is that unclear?

Let's say you are writting a db client package and a service around it.

The package's db.Exec(query) method should return and error that will have an error text received from db if any AND\OR context from the package itself.

Then in your service you add additional context to this error if needed.

Finally you log your typical "failed to write HackerNews comment do db with err: %db_package_context: db_error_text_here%"

>6

Not sure about "most" loggers, but I have no problem with zap. Popular, definetelly can be injected etc.

Re: Gopher Wrangling: Effective error handling in Go

#145
post #91

Could someone explain why is Go so hyped? In my personal opinion it is just not a good language, and I think many judge it based on some false basis that it is somehow “close to the hardware” because it produces a binary. Like, the amount of time it is put next to Rust when the two have almost nothing in common.. It is very verbose, yet Java is the one that is called that, often by Gophers, which is much more concise…

I'm strongly convinced that the google brand name gave it a big push. Its predecessor (Limbo if I recall correctly) went nowhere. It did bring uncolored async to the mainstream, but as in typical golang fashion, it was very verbose and error prone.

Java learned the right lessons and I'm quite excited to see their structured concurrency approach. No need to pass channels and contexts everywhere to manually manage hierarchies from what I gather.

Re: Gopher Wrangling: Effective error handling in Go

#146

The provided examples highlight exactly why error handling in golang is verbose, error prone, and lacks context. Do people really not care about stack traces?

Perhaps simple language and lack of abstractions lead to less code reuse so you can more easily tell where a particular error is coming from without context (less possible code paths).

Re: Gopher Wrangling: Effective error handling in Go

#147
post #91

Could someone explain why is Go so hyped? In my personal opinion it is just not a good language, and I think many judge it based on some false basis that it is somehow “close to the hardware” because it produces a binary. Like, the amount of time it is put next to Rust when the two have almost nothing in common.. It is very verbose, yet Java is the one that is called that, often by Gophers, which is much more concise…

I feel like a lot, if not all, has to do with the Google backing. Back when Go was announced, the company had _a lot_ of goodwill, and were envied by anyone doing software engineering. So, pretty much anything they did had an immediate following and base of engineers willing to blindly adopt whatever they did.

Maybe, but then look at Dart - a Google language whose real-world application so far has been the niche of Flutter app development.

I suspect it's a bit more than the Google stamp of approval - the innate simplicity of the language is attractive, it has almost Python-like simplicity without the performance concerns, and it has a "one true way" approach to formatting that settles any bikeshedding arguments in dev teams.

It's not my personal favourite language - the poor error handling discussed in this thread, the mess of the package management system (I mean, Python has a mess of a package management system, but that's more forgivable in a language from the 1990s, not the 2010s), the lack of decent standard library collections, etc. But I can see the appeal.

Re: Gopher Wrangling: Effective error handling in Go

#148
post #91

Could someone explain why is Go so hyped? In my personal opinion it is just not a good language, and I think many judge it based on some false basis that it is somehow “close to the hardware” because it produces a binary. Like, the amount of time it is put next to Rust when the two have almost nothing in common.. It is very verbose, yet Java is the one that is called that, often by Gophers, which is much more concise…

Go is hyped because it's amazing to work with. It's clean, simple, readable, very powerful and fast, has goroutines and a ton of libraries which are very easy to get,

Re: Gopher Wrangling: Effective error handling in Go

#149
Majority of people who complain about errors in Go don't primarily work with compiled languages that produce programs that run indefinitely or for a very long periods of time. It's easy to throw exception in PHP which is interpreted on the fly and run once so any failure can be simply thrown out and ignored. With constantly running programs one has to always handle all the cases where things don't go as wanted to prevent program form crashing. If people truly hate Go's errors, just panic, it's literally no different than exceptions in other languages. You can catch them and stop or continue whatever code you want. Just STFU about errors in Go already!

Re: Gopher Wrangling: Effective error handling in Go

#150
post #76

Earlier quoted context omitted.

So what is the point of the distinction then? The examples I gave were idomatic Rust too. Both Go and Rust hand the caller an error and the caller then must do something with the error. In both Go and Rust, you can assign the error to underscore and ignore it. Java is different but we aren't talking about Java right now. The only difference is that in Go the function can (and must) still provide a value for "file" ev…

> Both Go and Rust hand the caller an error and the caller then must do something with the error. This is simply not true. Go preaches that values should always be useful. Given a return signature (T, error), the value of type T can be used irrespective of what is contained in the value of type error. They are independent states. > The only difference is that Go provides a value for "file" when there is an error. Yes…

> Go preaches that values should always be useful

This is already false. Not all values are useful, for example, the value of this string is not useful to you: "i have cheese".

Without knowing the caller, values can be "possibly useful" at best.

> Often they will be dependent for all practical purposes. It is not an unreasonable assumption to assume that they are, especially if you know the caller. However, Go believes you cannot make that assumption. That you have to let the caller determine what it finds useful, not what you think it might find useful.

In Go, functions always assume the caller needs both a valid value of T and error, even when T has no value. Functions should synthesize some value for T should T not currently have a value at return time.

In Rust, most functions assume the caller needs either a valid value of T or Error. Should a valid value of T exist at return time, it will be discarded.

Both languages make assumptions.

> Tradeoffs, as always.

Assumptions come with tradeoffs, however, not all tradeoffs are equal in consequence and possibility.

99% of the time, a caller does not need T if there is an Error. Therefore, why make this tradeoff?

Post reply on HN