Live data from Hacker News

Gopher Wrangling: Effective error handling in Go

stephenn.com

101–110 of 310 posts

Re: Gopher Wrangling: Effective error handling in Go

#101
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.

Re: Gopher Wrangling: Effective error handling in Go

#102
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 think this claim is too reductionistic to go anywhere. There is no single thing that can explain go’s success. There are hundreds of small differences in the language (and tooling, which arguably is more important).

Most people are not going to care enough (or have the time) to enumerate every single difference between go and Java, and why they prefer the trade off go makes. I use Java professionally, and go where I can, and there is a lot I prefer about go (I won’t pretend it’s uniformly better, though.)

And fwiw, me and you have gone back and forth about this question in many threads previously. I think asking it from such a high level is not going to very effectively get into the details that actually matter to people.

Finally, I also think a lot of what makes go preferable is not in the realm of language design (at least not the algebraic type theory kind) or specific features. It’s much squishier than that, and involves feelings about how teams work and what developers do in practice (and why they fail).

Re: Gopher Wrangling: Effective error handling in Go

#103
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.

I don’t buy it. I can’t think of a single other Google backed programming language with anywhere near to the following of Go.

I think Googles stamp gives it some legitimacy, but I think the much likelier explanation is that the values in Go and its design speak to frustrations a lot of people actually have. This thread is full of people arguing in favor of gos error handling. You can dismiss them all as cranks or sheep if you want, but I think that would be misunderstanding something.

Re: Gopher Wrangling: Effective error handling in Go

#104
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.DeadlineExceeded` where it should've said `errors.Is(err, context.DeadlineExceeded)` as it's a good practice to always assume that exceptions may get wrapped (#4 just mentioned that).

Re: Gopher Wrangling: Effective error handling in Go

#105
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 think this claim is too reductionistic to go anywhere. There is no single thing that can explain go’s success. There are hundreds of small differences in the language (and tooling, which arguably is more important). Most people are not going to care enough (or have the time) to enumerate every single difference between go and Java, and why they prefer the trade off go makes. I use Java professionally, and go where…

Then let me ask instead: why does Go hit the HN front page each day? I would say Rust used to be/is similarly hyped, but it is sort of understandable there, as it is built on a novel idea and fits a previously unoccupied space.

This is not true of Go, and we could just as well see just as many D, Java, C#, Haskell, OCaml posts, yet they combined are not as frequent “visitors”.

Re: Gopher Wrangling: Effective error handling in Go

#106

Earlier quoted context omitted.

Less than I thought I would. I work with a very large Go codebase, and I don't remember the last time I had problems because I needed a stack trace. Just grepping for the error message is enough to show me exactly where it happened. Still, this doesn't mean that Go does not have stack traces. It does have stack traces for panics, and you can create stack traces by wrapping errors.

I frequently am sad about the kind of Rust error that doesn't have stack traces. Do you not often see something like "file not found" and need to know what file wasn't found? Or do the lowest level go error types carry more context?

[deleted]

Re: Gopher Wrangling: Effective error handling in Go

#107

Earlier quoted context omitted.

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.

I don’t buy it. I can’t think of a single other Google backed programming language with anywhere near to the following of Go. I think Googles stamp gives it some legitimacy, but I think the much likelier explanation is that the values in Go and its design speak to frustrations a lot of people actually have. This thread is full of people arguing in favor of gos error handling. You can dismiss them all as cranks or she…

I mean, maybe - but there's a lot of examples of things being as popular as they are because google did them - gRPC, Protobuf, Kubernetes, Chromium.

None of these things were technically bankrupt (including Go), but their adoption curve would not have been what they have been without Googles name on it.

There's likely other OSS that's technically better, but did not have the network effects google-backed software had from day 1.

Re: Gopher Wrangling: Effective error handling in Go

#108

Earlier quoted context omitted.

Less than I thought I would. I work with a very large Go codebase, and I don't remember the last time I had problems because I needed a stack trace. Just grepping for the error message is enough to show me exactly where it happened. Still, this doesn't mean that Go does not have stack traces. It does have stack traces for panics, and you can create stack traces by wrapping errors.

I frequently am sad about the kind of Rust error that doesn't have stack traces. Do you not often see something like "file not found" and need to know what file wasn't found? Or do the lowest level go error types carry more context?

The programmer needs to be aware that they will need to provide enough context in case of a failure. One thing I see a lot in Go examples is this pattern:

  body, err := readFile(fileName)
  if err != nil {
    return "", err
  }
If the error returned by readFile is just "not found", it would indeed be very vague. This is still poor error handling, in my opinion, since a lot of the context is lost. Yes, they are "handling" the error, but only enough to stop the linter from complaining. I prefer something like this:

  body, err := readFile(fileName)
  if err != nil {
    return "", errors.Wrapf(err, "readFile(%s)", fileName)
  }
This would result inan error like this:

  readFile(file.txt): not found
This way I get all the context I need to know where the error happened and the arguments that caused the error.

If the error happened not because of a function call, but, say, an invalid value, instead of this:

  if n 
Do this:

  if n 
In languages like Java, it feels very tempting to let errors bubble up and then let the stack trace take care of explaining what went wrong, but it is often insufficient and may result in hours of debugging. I feel like Go makes it very easy to add extra context to errors, and if you foster the practice of adding context every time you return an errlr, it will be much richer than a stack trace.

Re: Gopher Wrangling: Effective error handling in Go

#109
post #94

Earlier quoted context omitted.

> This is trying to twist a weakness of Go's type system as a virtue. No. There is no discussion about type systems taking place here at all. The discussion is about patterns where the producer or the consumer is in control. Specifically, Result puts the producer in control. Idiomatic Go (T, error) sees the consumer in control. There is likely no language in existence that prevents you from choosing. You can write co…

This entire discussion is about the type system and how it interacts with the language. Go does not have sum types, so the producer cannot signal to the consumer what it can produce and what the consumer has to handle. The consumer in Go must pessimistically assume the all combinations of return values are possible, where in a language with a decent type system the possible cases can be enumerated and handled appropr…

> This entire discussion is about the type system and how it interacts with the language.

No. The discussion opened to say that Result is better than the pattern used in Go. In other words, dependent state is better than independent state. I said that dependent state puts the producer in control, while independent state puts the consumer in control and that there are pluses and minuses to each approach, with neither being better, just different tradeoffs.

We continued to discuss that control and how Result, exceptions, and the (T, error) pattern play into that. Somewhere in the middle was a regularly scheduled Rust advertisement, but following that returned to the same topic. A topic that is not, and never has been, about type systems. And it isn't even about any particular programming language, even if Go was used to call out a pattern that the original commenter didn't have a better name for.

> If your producer does not match that, you are not forced by the language to use Result.

So, in other words: Dependent state puts the producer in control, while independent state puts the consumer in control and that there are pluses and minuses to each approach, with neither being better, just different tradeoffs...?

It is curious how the word Go causes minds to shut down.

Re: Gopher Wrangling: Effective error handling in Go

#110
post #77
post #32

Earlier quoted context omitted.

In what sense aren't they monads? They have a bind method ("and_then") and a return method (Which is just the variant for constructing the success case, i.e. "Ok" or "Some"). It's more idiomatic to use "map", but that's just a degenerate case of bind. > There's some tricks that have to be done to make them work in a eager evaluation context... Monads have nothing to do with laziness, though. In Haskell, IO actions ar…

After doing some research to refresh my memory I found this old thread: https://users.rust-lang.org/t/what-is-a-monad-and-who-needs-... I believe what I had originally told that makes them not monads is that because Rust goes through some convlutions to fake the laziness of Haskell monads, it makes them not be typed like Haskell monads. For example, the declaration of the `.flat_map` on an iterator is actually `fn fl…

Ah interesting. I think it's close enough as to make no difference, but I see what you're saying.
Post reply on HN