6 ms·
An exception has a stacktrace. This single piece of information is crucial when you debug and makes handling errors in Golang embarrassing. I rest my case.
by linkdd 5y ago
An exception has a stacktrace. This single piece of information is crucial when you debug and makes handling errors in Golang embarrassing.
I rest my case.
- mseepgood 5y agoIf you want stacktraces just panic. But that's not proper error handling.
- divan 5y agoOr just print stacktrace with `debug.PrintStack()`
- pkaye 5y agoStack trace was part of a proposal to add to the error package but it didn't happen. You can use third party errors packages like https://github.com/pkg/errors https://github.com/pkg/errors which wrap errors with stack traces.
- randomdata 5y agoGo exceptions do carry stack trace information. However, the topic is errors, not exceptions. Those are very different concepts. Of what use is stack trace information in debugging values that you have assigned error meaning to when not other types of values? If you had a function func add(a, b int) int { return a * b } there would be no expectation of carrying a stack trace to debug it. So what's different about func add(a, b int) error { return errors.New("cannot add") } that does require a stack trace?
- dragonwriter 5y ago> However, the topic is errors, not exceptions. Idiomatically, go uses errors for the purposes other languages use exceptions, so if this makes debugging harder, it's an important consideration.
- randomdata 5y agoThat is also true of most languages. Java (and Javascript in its attempt to copy it) are about the only languages that actually promote using exceptions for errors, and in hindsight I think we can agree it was a poor design decision. That doesn't stop people from trying to overload exceptions in other languages, Go included, but in terms of what is idiomatic... However, the question was asking what is different about errors compared to other values. The add function above contains an error, yet I don't know of any language in existence where you would expect a stack trace bundled alongside the result to help you debug it. Why would that need change just because you decided to return a struct instead of an int? And actually, many APIs in the wild do represent errors as integers.
- dragonwriter 5y ago> Java (and Javascript in its attempt to copy it) are about the only languages that actually promote using exceptions for errors Python does. Ruby does. It's not just Java and JS. Go is very open about its approach being a departure. > And actually, many APIs in the wild do represent errors as integers. Many, many APIs in the wild are implemented in (or meant to be consumed from) C, which doesn't even have exceptions, so not using exceptions makes sense for them. Very often idiomatic non-C host language wrappers for those APIs will fire exceptions when they get an error return.
- randomdata 5y ago> Ruby does. Definitely not. Especially because early Ruby implementations brought huge overhead when exceptions were used, you were strongly advised to only use exceptions for actual exceptions. Ruby was one of the first languages that really started pushing the idea that exceptions should be reserved for exceptions, even if was just for technical reasons. Those overhead problems have been addressed and are no longer a problem, but the sentiment has continued to ring true. I agree that doesn't stop people from trying to overload them, as I said earlier. But idiomatic? Not at all.
- 5y ago
- linkdd 5y agoCurrent state of the art: func read_file(filename string) (string, error) { return "", errors.New("oops") } func foo() error { a, err := read_file("a.txt") if err != nil { return errors.New(fmt.Sprintf("read a: %s", err)) } b, err := read_file("b.txt") if err != nil { return errors.New(fmt.Sprintf("read b: %s", err)) } // do stuff with a and b return nil } func main() { err := foo() if err != nil { fmt.Fprintln(os.Stderr, err) } } In a language with exceptions: func read_file(filename string) string { throw FileNotFound(filename) } func foo() { a := read_file("a.txt") b := read_file("b.txt") // do stuff with a and b } func main() { try { foo() } catch (err FileNotFound) { fmt.Fprintf(os.Stderr, "file not found: %s\n%s\n", err.filename, err.Stacktrace()) } } With the current go error handling, you need to add the informations yourself in the string, not as a real data structure. And before you say "you can add the filename to the error message in read_file()", what if the function is defined in a dependency you have no control over? An exception is a typed data structure that contains way more informations and value to automate rescuing. Delegating error handling to a try/catch block with a typed data structure allows the caller to care for certain type of errors and delegate the others to its own caller. With the current error type in Go, what would you do? parse the error message?
- randomdata 5y agoYour code is wrong. It would normally be written something like this: func read_file(filename string) string { panic(FileNotFound{filename}) } func foo() { a := read_file("a.txt") b := read_file("b.txt") // do stuff with a and b } func main() { defer func() { if err, ok := recover().(FileNotFound); ok { fmt.Fprintf(os.Stderr, "file not found: %s\n%s\n", err.filename, err.Stacktrace()) } } foo() } However, exceptions are meant for exceptional circumstances (hence the name), not errors. A file error is not exceptional in the slightest. It is very much expected. While you can overload exceptions to pass errors (or any other value), that does not mean you should. Your use of exceptions for flow control (i.e. goto) is considered harmful.
- linkdd 5y ago
- geodel 5y agoYea, I am not really fan of 1000 line stack trace for an error in single line. I like Go's error handling better. Also it is clear you like error handling in Rust/Java etc which is fine. Exaggerating over how bad error handling in Go is hardly productive when a) many people do like it b) people can switch language when error handling primary concern over everything else.
- kaba0 5y agoHow will you fix that bug in production when you can’t reproduce it and only has logs? Stacktraces are godsend.
- geodel 5y agoWell as I said people do like stack traces. Hell, I work on language which just has exception stack traces as error handling. I find it hit and miss not godsend when fixing production issues.