Live data from Hacker News

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

github.com

41–50 of 61 posts

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

#41

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.

That's not exactly true. All struct types in Go can not be nil. However, they also can't be abstracted over in any way, so they are a poor idea for an error type - you want an error interface, and all interface types in Go indeed are nil-able.

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

#42

Have spent a while in the py/js world but have switched to rust/go for part of this year -- biggest change is boilerplate relating to error handling. Automatic stack capture for exceptions is something my language could conceivably do on my behalf. Writing even 3 lines of code per function to propogate up the error is a huge pain, especially because it pollutes the return type -- MustWhatever() in go is much easier t…

Go is just a half-baked joke language. Neither generics nor proper error handling nor a proper type system - whoever uses that crap just because it was made by Google is wasting their time. The only thing Golang has been succesful at is proving Google is well-capable of releasing and marketing absolute unadulterated crap. Just use the JVM or .NET Core...

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

#43
post #39

Earlier quoted context omitted.

What surprises me as a primarily JVM developer now supporting Go apps and dabbling in Go development is that the logging libraries (like klog) I've encountered don't support the level of configuration I'm used to in JVM apps. I miss being able to configure individual loggers at desired levels with a logback.xml in the JAR, but especially the ability to change logging levels at runtime. I guess it's part of the Go phi…

You might wanna look at using something like zap instead, as it enables you to do runtime loglevel changes...

Cheers for my development, I'll do that :)

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

#44
post #12

Earlier quoted context omitted.

Rust has a postfix `?` operator to propagate errors up the call stack.

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

You can use the Error trait [1] from the stdlib, implement it for your error types and then just use the trait in your Result. That way you don't need the types to match and you can convert between then as needed while adding the previous errors to the chain.

1. https://doc.rust-lang.org/std/error/trait.Error.html

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

#46

Earlier quoted context omitted.

Of course you can. Sad path first means, after you write your data types and interface signatures, writing the first stub implementations as func (t *Thing) Process(id int) (string, error) { return "", fmt.Errorf("not implemented") } and then filling them in gradually like func (t *Thing) Process(id int) (string, error) { dat, err := t.store.Read(id) if err != nil { return "", fmt.Errorf("error reading ID: %w", err)…

Sure, but in a better language, the second version already does the exact same thing as the first one. Your `return fmt.Errorf` is not exception handling, it is simply manual exception bubbling. It is boilerplate that you can forget to add, and that makes it harder to understand what the code is supposed to do. Maybe for the first error you are adding some context that the Read function didn't have, but for the secon…

`If they wanted to handle the certificate error but not the read error, they would have to parse the error message string, which is brittle.` Aaargh that is my main pain with Go error handling. I try to have an open heart with all the verbose way of living, but this "select by error type" when I want to treat errors really feels awkward

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

#47
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 =…

Try golangci-lint it catches all your use case.

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

#48

Earlier quoted context omitted.

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

That's not exactly true. All struct types in Go can not be nil. However, they also can't be abstracted over in any way, so they are a poor idea for an error type - you want an error interface, and all interface types in Go indeed are nil-able.

You can abstract over a struct as easily as a pointer, and structs work fine for satisfying interfaces. Specifically, structs make it a little harder for someone to inadvertently mutate things (passed by copy) and because they can’t be nil you don’t need to worry about a non-nil interface implemented by a nil concrete pointer (this is mostly only a problem for people who are new to pointers in my experience). The downside is every time you put a struct into an interface, it gets allocated on the heap, and allocations are expensive in Go (also passing structs can be more expensive than passing pointers).

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

#49

Earlier quoted context omitted.

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

> Yes, it does. Whenever you call a function that can possibly fail, you are supposed to add: if err != nil { return err }

I don’t think that’s what the parent meant by his question. He was asking if you have to add runtime checks all over to make sure any reference type isn’t nil; no, you don’t—you only add the checks for those for which nil is a valid state in the program (such as errors). If it’s an invalid state, it will panic because it’s an exceptional circumstance—a programmer error. This isn’t a defense of nil; only a clarification about how nil is dealt with. With this context, the rest of his question (the part you didn’t understand) becomes clearer.

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

#50
post #44

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

You can use the Error trait [1] from the stdlib, implement it for your error types and then just use the trait in your Result. That way you don't need the types to match and you can convert between then as needed while adding the previous errors to the chain. 1. https://doc.rust-lang.org/std/error/trait.Error.html

ah thanks
Post reply on HN