4 ms·
> How do you reconcile that with the general rule or convention that `if err != nil` the value is unsafe to use? By reading the documentation: https://pkg.go.d
by bheadmaster 3y ago
> How do you reconcile that with the general rule or convention that `if err != nil` the value is unsafe to use?
By reading the documentation: https://pkg.go.dev/io#Reader https://pkg.go.dev/io#Reader
Conventions are not laws, and should not be followed blindly.
> What I do think is feasible is adding some more syntax sugar around errors.
The most common example I hear is something like Rust's `?` operator for propagating errors. In Go, errors should almost always be expanded with additional context, and programmers should think hard about errors and how to handle them. Syntax sugar would just make it easier for people to ignore errors. And you can't ignore errors forever - they always come up, most often in the place you least expect them.
- the_gipsy 3y ago> In Go, errors should almost always be expanded with additional context I'm convinced this is just a very poor way to cope with the lack of stacktraces.
- bheadmaster 3y agoActually, stack traces are a very poor way to provide context. I can't count how many times I've worked with some library in ${LANGUAGE_WITH_EXCEPTIONS}, and had an exception print out a giant stack trace, only for me to realize that the stack trace is useless because the place where exception is raised isn't the place where the error actually happened, but is actually some wrapper/worker collector/other kind of indirection mechanism. In other words, stack traces are directly bound to call stacks, and call stacks don't necessarily contain all relevant context of an error - they only do so in case of simple, single-threaded programs. Golang-style error-as-values actually provide real, human-curated context that is relevant to the operation at hand. They can be passed between goroutines, and are completely independent of any call stacks. That, in my opinion, makes them vastly superior to stack traces.
- the_gipsy 3y agoIt's true that stacktraces don't work out so well in many languages. But ironically in go they do seem to work fine in my experience. Adding a stacktrace to custom go errors do show me correct and useful traces across goroutines. I guess it's the fact that async is built into the language as a primitive or something. Regarding wrapping errors, if you don't provide a stacktrace or at least file:line, how do you actually map the error to source code? Do you just grep and pray that the message is unique enough?
- bheadmaster 3y ago> Do you just grep and pray that the message is unique enough? If you're new to the codebase, yes, grepping can get you a long way. In my experience, just following the error messages from the top (usually errors are printed only in the main function) is enough. Hypothetical example, if you have a file sync program, and you get an error "file sync failed: device Foo unreachable: connect error: quic://123.45.67.89/ i/o timeout", you can already mentally map where exactly the error has happened. The exact file and line should be easy to locate. Of course, if a codebase doesn't write descriptive enough errors, or just propagates them without context, error diagnosis is going to be difficult. But that's why Go encourages people to think about errors and not ignore them.