Live data from Hacker News

Eris – A better way to handle, trace, and log errors in Go

github.com

21–30 of 61 posts

Re: Eris – A better way to handle, trace, and log errors in Go

#21

Earlier quoted context omitted.

It's not just a pain to write. I've accidentally introduced way more bugs through Go style error handling than through Python style error handling. Some examples: Forgetting that a function returns an error: ... foo() // foo returns an error that isn't being handled. ... Forgetting to check the error returned by a function. Note a linter won't pick this up since the err variable is used later. ... err := foo() err =…

> All of these issues look just like normal bug free Go code. Not to me.

ok

Re: Eris – A better way to handle, trace, and log errors in Go

#22
post #14

Earlier quoted context omitted.

I don’t buy the “huge pain” argument. I write lots of Python and Go, and the error boilerplate is a non-issue. I also appreciate that it’s explicit instead of implicit.

It's not just a pain to write. I've accidentally introduced way more bugs through Go style error handling than through Python style error handling. Some examples: Forgetting that a function returns an error: ... foo() // foo returns an error that isn't being handled. ... Forgetting to check the error returned by a function. Note a linter won't pick this up since the err variable is used later. ... err := foo() err =…

Having written maybe two lines of Go, many years ago, I guess I'm surprised that all of these cases make it past the type system. Like shouldn't it bitch if you try to return nil when it's expecting a non-nil value or an error? I guess I'll go try to find an online go thinger to find out.

Re: Eris – A better way to handle, trace, and log errors in Go

#23

Earlier quoted context omitted.

It's not just a pain to write. I've accidentally introduced way more bugs through Go style error handling than through Python style error handling. Some examples: Forgetting that a function returns an error: ... foo() // foo returns an error that isn't being handled. ... Forgetting to check the error returned by a function. Note a linter won't pick this up since the err variable is used later. ... err := foo() err =…

Having written maybe two lines of Go, many years ago, I guess I'm surprised that all of these cases make it past the type system. Like shouldn't it bitch if you try to return nil when it's expecting a non-nil value or an error? I guess I'll go try to find an online go thinger to find out.

There’s no way to tell Go that a value shouldn’t be nil.

Re: Eris – A better way to handle, trace, and log errors in Go

#24

Earlier quoted context omitted.

Having written maybe two lines of Go, many years ago, I guess I'm surprised that all of these cases make it past the type system. Like shouldn't it bitch if you try to return nil when it's expecting a non-nil value or an error? I guess I'll go try to find an online go thinger to find out.

There’s no way to tell Go that a value shouldn’t be nil.

Thanks for the info!

And... Woah. That's kind of horrifying to me (though I totally get the explicitness of it)... does this just mean liberal amounts of: thing != nil everywhere? Or is the rest of the memory management I guess, uhh.., good/magical enough you don't have to worry about it constantly in calls further down the stack if you've checked it once? Or are you always feeding the nil check beast?

Re: Eris – A better way to handle, trace, and log errors in Go

#25
post #18

Earlier quoted context omitted.

as I understand it, this requires an Option or Result return type that matches the type of the statement The ? operator is better than nothing, but I still need my error types to match all the way up the stack

AFAIK if you properly define the From/To operator, rust generates it for you. And if you think about it, defining those operator is a good practice as it tells your program how to handle errors.

Or you can use a boxed error iirc. Matching on the type of error after you do that isn't exactly great but it's doable if all you want to do is bubble the error up.

Places where that approach really sucks include web api routes (unless I haven't figured out a trick yet). For example, rocket defines Responder on Result so long as the ok and error variants both define it, but since a boxed error is erased it doesn't function correctly.

Re: Eris – A better way to handle, trace, and log errors in Go

#26
post #14

Earlier quoted context omitted.

I don’t buy the “huge pain” argument. I write lots of Python and Go, and the error boilerplate is a non-issue. I also appreciate that it’s explicit instead of implicit.

It's not just a pain to write. I've accidentally introduced way more bugs through Go style error handling than through Python style error handling. Some examples: Forgetting that a function returns an error: ... foo() // foo returns an error that isn't being handled. ... Forgetting to check the error returned by a function. Note a linter won't pick this up since the err variable is used later. ... err := foo() err =…

I don’t know man. I have scarcely seen bugs like these and most of them seem pretty conspicuous to me (maybe I’ve just been writing Go long enough), but I see loooads of uncaught Python (and Java) exceptions internally and from high-profile third party tools.

Re: Eris – A better way to handle, trace, and log errors in Go

#28

Earlier quoted context omitted.

It's not just a pain to write. I've accidentally introduced way more bugs through Go style error handling than through Python style error handling. Some examples: Forgetting that a function returns an error: ... foo() // foo returns an error that isn't being handled. ... Forgetting to check the error returned by a function. Note a linter won't pick this up since the err variable is used later. ... err := foo() err =…

> All of these issues look just like normal bug free Go code. Not to me.

I don't know. They're hard for me to find. How would you pick up on the first and last example? They are possibly correct depending on the exact functions you are calling.

The other two examples, I could maybe understand, but they still look pretty close to normal Go code. In the case where you forget to handle an error, you need to be able to recognize the absence of the error checking bit. It would be one thing if there was extra code that looked wrong, but looking for the absence of code makes it hard to spot.

In the case where you return nil, it looks exactly like a normal early-exit from a function. You need to be able to recognize that the code is not a normal early-exit, and that the three letters "err" were swapped for the three letters "nil".

Re: Eris – A better way to handle, trace, and log errors in Go

#29

Earlier quoted context omitted.

There’s no way to tell Go that a value shouldn’t be nil.

Thanks for the info! And... Woah. That's kind of horrifying to me (though I totally get the explicitness of it)... does this just mean liberal amounts of: thing != nil everywhere? Or is the rest of the memory management I guess, uhh.., good/magical enough you don't have to worry about it constantly in calls further down the stack if you've checked it once? Or are you always feeding the nil check beast?

> does this just mean liberal amounts of: thing != nil everywhere

Yes, it does. Whenever you call a function that can possibly fail, you are supposed to add:

  if err != nil {
      return err
  }
You can think of it as unwinding the stack by hand. That's why a lot of people complain about Go error handling so much. That and a lack of generics. Looking at some code I've written, about 15-20% of the lines in a file are responsible for error handling.

> Or is the rest of the memory management I guess, uhh.., good/magical enough you don't have to worry about it constantly in calls further down the stack if you've checked it once?

I don't quite understand the question here. Are you asking about a performance impact of having nil checks everywhere? If I had to guess, I would think there's a negligible performance impact because the branch predictor will always predict the happy case. As for memory concerns, as long as you are in the happy case and returning nil, no memory needs to be allocated. It's the same reason null doesn't require any memory allocation in other languages.

Re: Eris – A better way to handle, trace, and log errors in Go

#30
post #26

Earlier quoted context omitted.

It's not just a pain to write. I've accidentally introduced way more bugs through Go style error handling than through Python style error handling. Some examples: Forgetting that a function returns an error: ... foo() // foo returns an error that isn't being handled. ... Forgetting to check the error returned by a function. Note a linter won't pick this up since the err variable is used later. ... err := foo() err =…

I don’t know man. I have scarcely seen bugs like these and most of them seem pretty conspicuous to me (maybe I’ve just been writing Go long enough), but I see loooads of uncaught Python (and Java) exceptions internally and from high-profile third party tools.

That's very possible. It's very easy to forget try...catch and wind up with uncaught exceptions.

Honestly though, I would prefer the uncaught exception case. When an uncaught exception is thrown, it's very clear you have an uncaught exception and you know exactly where it came from. In the examples I wrote, you will accidentally catch an error silently. You will never know if anything went wrong unless silently catching the error triggers an issue somewhere else. Even then, it's pretty hard to trace back the bug to the lack of error handling code somewhere else.

Post reply on HN