4 ms·
So basically they're proposing: f, err := os.Open(filename) if err != nil { return …, err // zero values for other results, if any } can be simplif
by hliyan 7y ago
So basically they're proposing:
f, err := os.Open(filename)
if err != nil {
return …, err // zero values for other results, if any
}
can be simplified to
f := try(os.Open(filename))
This makes a lot of sense, but I'm of two minds. On one hand, it makes things much cleaner. On the other hand, it might be a first step onto a slippery slope that ends with exceptions.
A lot of others chiming in with different ideas on the original ticket: https://github.com/golang/go/issues/32437 https://github.com/golang/go/issues/32437
- jerf 7y agoAfter chewing on this for a while, I've come to the conclusion that the thing exceptions does wrong (or if that is too controversial, substitute "most dangerously") is that it disconnects handling the error from the scope that generated it. It's the way exceptions so easily fly up the stack into code that can't understand them because it is too distant in context that is the problem. Neither this proposal, nor any other I saw, would change that. I wouldn't even call this "a step in the direction of exceptions"; it's a neutral move. Everything is still occurring within the same scope, it's just getting spelled differently. Interestingly, this means that while pervasive use of "if err != nil { return err }" is technically very similar to exceptions when used everywhere, it can still have a different semantic meaning to a human reading the source.
- captncraig 7y agoEvery time I switch back to exception languages, I get this tendency to "assume everything succeeds all the time, and handle it at the very top level in case any part of it fails". I do not think about what can go wrong at each level nearly as much as I do when I am required to use `if err != nil` soup.
- nprateem 7y agoExactly. And in most cases I don't care. Can't open that file? That's a fatal error. Can't connect to the DB? That's a fatal error. Some file system operation failed? That's a fatal error. In the majority of applications it's normally pretty obvious which errors you're likely to care about (the user already exists, etc.) vs the rest that you just handle at the top level. The trouble with go's error handling is it makes you care about everything, which is just a waste of time and effort because the majority of errors will be fatal anyway.
- dickeytk 7y agoI completely agree. I love that go is _able_ to treat errors just like return values but most of the time I don't need to work with them like that. I want to assume the happy path and not have all the `if err != nil` noise.
- twblalock 7y ago> Every time I switch back to exception languages, I get this tendency to "assume everything succeeds all the time, and handle it at the very top level in case any part of it fails". I do not think about what can go wrong at each level nearly as much as I do when I am required to use `if err != nil` soup. This is generally the best way to deal with errors. In most cases, only the original caller really knows which errors ought to be considered fatal, and which should result in retries or be handled in some other way. If you handle errors deep down in the call stack, you are robbing the caller of the ability to decide how to handle them. Different callers may want different things. It is better to let errors bubble up as far as possible.
- tonyedgecombe 7y agoYes, I like that part of exceptions. I can hold more of the problem in my mind when I don’t need to worry about what happens when something exceptional happens.
- lazulicurio 7y ago> Every time I switch back to exception languages, I get this tendency to "assume everything succeeds all the time, and handle it at the very top level in case any part of it fails" See, I get the exact opposite tendency. Exceptions mean that any statement, no matter how seemingly trivial from the caller's perspective, can fail. It means I'm constantly thinking "If an exception is thrown between X() and Y(), does it break any assumptions I've made about the program state?". You end up with hacks like putting code in finally blocks just to prevent partial execution. I think exceptions would work fine in a language that also had built-in support for transactional memory, where you could commit or rollback operations when an exception is thrown partway through. Without any language support, though, I think that exceptions and mutable state do not play nicely with one another.
- kjeetgill 7y agoComing from Java I agree: that's what tends to happen, but I miss it when I don't have it. It's helpful habit for services especially because most of what you're doing is local to a request anyway and you want to "undo" or "drop" things. Exceptions in services are great because they actually preserve situational information pretty well and a catch+rethrow is pretty good for annotations at different levels. Err/panic are so poor at capturing anything of value by default. They require a ton of diligence to be useful. The nice thing about being able to catch exceptions is that I can kinda define what operations are "atomic" on my terms. Presumptuous example disclaimer. For instance, if I'm processing a set of files with records, I'll probably have a substantial error domain around the processing of a record, of a whole file, and my whole program. I don't want to babysit each byte read. Now, I admit, this does require you to write code that didn't pollute your state with partial work. Unwinding from a frame/function should leave everything in a known place.
- coldtea 7y ago>I get this tendency to "assume everything succeeds all the time, and handle it at the very top level in case any part of it fails" Which is not bad at all. In fact, it's closer to how e.g. Erlang works.
- dickeytk 7y agoon a side note, if I could just write `if err != nil return err` on a single line (without `go fmt` "fixing" it) that might be enough for me not to need `try`.
- deleted 7y ago[deleted]
- blacksmythe 7y ago>> without `go fmt` "fixing" it Great point. And this line should be indented relative to the 'happy path' lines!
- est31 7y ago> On the other hand, it might be a first step onto a slippery slope that ends with exceptions. Rust originally had a try! macro just like go and is slowly sliding down that very slope. Let's just say there is a split in the community about whether an exception like outside syntax is a good idea or not. Some like the idea, some don't like it. It yields in threads like this one: https://github.com/rust-lang/rfcs/pull/2426 https://github.com/rust-lang/rfcs/pull/2426
- josteink 7y ago> it might be a first step onto a slippery slope that ends with exceptions. Like that “slippery slope” with code generators leading to generics? To me it seems like golang-users actually wants all those features it’s language-designers took away.
- ailideex 7y ago> it might be a first step onto a slippery slope that ends with exceptions. And what? Why avoid exceptions?
- politician 7y agoThis is certainly following the path of JavaScript Promises which do, as you say, end in exceptions. It would be nice to skip directly to `try func() error{}()` and avoid that specific pain.
- coldtea 7y ago>On the other hand, it might be a first step onto a slippery slope that ends with exceptions. Or, you know, exceptions are the right slope, and the ad-hoc implementations of generics, error handling etc, is the slippery slope...