Live data from Hacker News

Gopher Wrangling: Effective error handling in Go

stephenn.com

271–280 of 310 posts

Re: Gopher Wrangling: Effective error handling in Go

#271

Earlier quoted context omitted.

Which proves that there is more load on the programmer to ensure that no two error messages are the same. What is this, are we back to programming in C with __LINE__ macros?

I believe the issue you're concerned about is relatively insignificant compared to your perception of its magnitude. But if this is something you are very concerned about, there are many approaches you can adopt in a Go codebase to make errors richer, such as using the "errors" package and a structure logger, which are enforceable at CI time and will give you stack traces.

Having worked on several large golang code bases, those issues popped up all the time. Yes we used the errors package, but as with the rest of the language, you end up having to reinvent the wheel poorly and in an error prone manner. Incidentally, that employer built their own golang framework with dependency injection and interception to modify error values, such a huge effort for something that comes out of the box with other languages, and it was still not on par with them.

Re: Gopher Wrangling: Effective error handling in Go

#272

Earlier quoted context omitted.

Nothing you wrote is specific to golang's error handling though, and in actuality, ends up being more brittle because it is possible to miss handling such errors. At least an exception would bubble up instead of keeping the program running in an undefined state.

it is my very clear experience that rust programs are more brittle than go programs, precisely because rust makes it possible (even encourages) error "bubbling" via `?` in practice, go code bases that are subject to even minimal code review have basically no ignored errors

yeah my linters won't allow it. and bubbling up is exactly what you dont want for robust code. the UX is different for a failure on rereading a config file when you already have a good config vs. on startup.

go code tends to be robust because the authors of the code and the community are the sort that worry about each err value, like Linux and like Python and like C itself.

Re: Gopher Wrangling: Effective error handling in Go

#273
post #202
post #45

Earlier quoted context omitted.

i wish people understood this thinking about and handling all errors, as a prime functiom of the code, is why things like Linux and C Python and X server and git and so on are so reliable.

The only reasons those are reliable is that they have millions of hours of runtime, so that the easier bugs have all been fixed now. If anything, they have become successful in spite of C.

they are successful in spite of the memory unsafety of C because of the culture that the behavior of a failing system is a principle feature of the code, which is common thinking in C and easier to do when you don't have the crutch of exceptions.

Re: Gopher Wrangling: Effective error handling in Go

#274
post #144

Earlier quoted context omitted.

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

>>3 > Why is that unclear? The usual advice is to follow what the stdlib does. Let's look at an example. Let's say we close a file and then try to set a deadline on it: f, _ := os.Create("/tmp/filename") f.Close() fmt.Printf("%v", f.SetDeadline(time.Now())) // output: use of closed file Okay, so in this case, it's the caller's responsibility to keep track of the filename and add the context of what file was already c…

I agree and I've been thinking about this in general (not only in the context of go, but for programming in general). I've settled on "caller adds context" because it is only the caller who knows if the error can be handled immediately (in which case no context is needed and we save the extra effort of creating it) or if the error should be propagated up, and how (should it be wrapped with context, wrapped in another struct, replaced with a different struct, etc).

Re: Gopher Wrangling: Effective error handling in Go

#275

Earlier quoted context omitted.

Unfortunately, fmt.Errorf makes errors.Is/As useless. In fact, errors.Is is mostly useless in general, since very few Go libraries have any error types at all. You're usually stuck with parsing error messages if you actually want to handle errors programmatically, even for much of the standard library.

Uh? If you use `%w` in fmt.Errorf(), it should still work with .Is and .As?

> Uh? If you use `%w` in fmt.Errorf(), it should still work with .Is and .As?

You still need a stable error to compare against in errors.Is. fmt.Errorf is not going to provide that if the message is dynamic - which is almost always.

Re: Gopher Wrangling: Effective error handling in Go

#276
I like that errors stay in the flow of control. No "Exception"s leaping up thru multiple levels of call stack. Instead the plan is: 1) see the error, 2) "%w" the error, 3) kick it upstairs, 4) Mission Accomplished. And at some level, some piece of code will grab the bull by the horns and wrestle it to the ground.

All in all, errors-as-values is a calm way to deal with unhappy code paths. A clear renunciation of longjump.

(Golang system-originated panics are excepted from this gloss, but they are defined quite narrowly, and ofc catchable.)

Re: Gopher Wrangling: Effective error handling in Go

#277

There was just so much nonsense back in the day around Go's error handling and about how it was so much more straightforward than adding exceptions to the language. In reality, the only reason why errors in Go work the way they do is that it kept the runtime simpler by offloading checking to the developer. The alternative would've been for Go to support sum types, which would've helped make error handling a lot saner…

nope! go's error handling is actually good! it turns out that treating errors the same as normal values makes programs more reliable lots of people get salty about it, for sure

The _right_ way to treat them as normal values is by using sum types.

So no, Go's error handling isn't at all good. 1.13 might've made them less execrable, but it didn't make it good.

Re: Gopher Wrangling: Effective error handling in Go

#278

Earlier quoted context omitted.

Is that a real stack trace, or just a trace of error message wrapping? I haven’t figured out how to extract a real error message using Go stdlib

No it’s a manual “stack” you build yourself with wrap. It’ll take you to the nearest error handler to the error which is usually not that far from the real problem

Ah yeah that’s what I figured. In some of the repos at work, I’ve noticed that some intermediate error messages are identical, which makes it hard to know which error has actually been used.

Re: Gopher Wrangling: Effective error handling in Go

#280
post #268

Earlier quoted context omitted.

This is why you can do const true = false in golang The number of reserved keywords is not a bad thing. For example, I constantly missed `final` when I worked in golang. Just because a keyword doesn't exist does not make its usecase disappear. Same with other features like `enum` (extremely useful) and visibility rules. golang only has package private and public, not nearly as granular as one needs in practice, not t…

> The number of reserved keywords is not a bad thing. I'm not saying reserved keywords are bad. I'm saying there's much more to learn about Java to learn programming, Go is limited with its' keywords and 'features', which often results in more LoC, but makes it super easy to get going, run into general programming problems like using a variable instead of a reference to it, etc. In Java, you spend much more time lear…

We should optimize for clear and concise code between experts. You’re going to be an expert for most of your career, and that’s when your time has the greatest value. A small learning curve is bad because you quickly run out of ways for tools to help you. I want to use the most powerful language I possibly can; the time investment pays off.
Post reply on HN