5 ms·
> In general, Go strongly encourages being explicit about errors. That's completely incorrect: it's trivial (and common) to just ignore errors in Go: ok,
by incepted 11y ago
> In general, Go strongly encourages being explicit about errors.
That's completely incorrect: it's trivial (and common) to just ignore errors in Go:
ok, _ := Foo()
Checked exceptions don't let you get away with this kind of sloppy programming.
- ngrilly 11y agoIt's also trivial to "just ignore errors" in a language based on checked exceptions: try { ok = foo() } catch (Exception e) { // Do nothing } Checked exceptions don't save you from "this kind of sloppy programming".
- Retra 11y agoAnd it'll happen frequently, because if you're just trying to test out `ok = foo()` and you're not sure if it'll work, then you've got to write four lines of awful boilerplate and go read an API reference just to get it to compile. Checked exceptions are supposed to encourage correctness, but there's no fudge room for playing around, so they are very not fun. As an aside, I once tried using a crypto library to do something fairly simple (encrypt a file I'm writing to disk), and I had to handle a whole stack of exceptions that I had no clue how to handle. So what can you do? You should be able to write code that provides sensible default behavior, but checked exceptions make you work to just get that behavior, which is not how default behavior is supposed to work.
- incepted 11y agoIf you don't know how to handle an exception, just add it to your `throws` clause and let a caller handle it. That's the whole point of exception: letting you choose who is the most appropriate to handle the error. Return value errors like Go implements forces everyone to care about all errors, at all times, even those they can't handle, which is why you see the pattern ok, err:= Foo() if err { every ten lines in Go sources.
- Retra 11y agoYou (the programmer) still have to handle it. If I (as a person) don't know how to handle the exception, passing it up the call stack doesn't solve the problem, it just moves it to somewhere else. The problem is that I don't know where it should be handled, because it was exposing cryptic and obscure exception types that probably make sense to someone who really understands cryptography. I don't, so I just can't use that library. If those were runtime exceptions, my program would just crash on error, which is the default I wanted. I didn't want to pollute my code with error handling stuff just to try out some simple functionality. If they were runtime exceptions, I could learn to use the code from the ground up, not by having to understand the whole thing at once.
- incepted 11y ago> it just moves it to somewhere else. That's exactly the point: not everyone along the method stack is forced to deal with it, only the one caller that knows how to handle it. > The problem is that I don't know where it should be handled Then don't handle it at all and let it crash the program. But at least you didn't add boiler plate simply bubbling up an Err at every level of the stack frames. > If those were runtime exceptions, my program would just crash on error, which is the default I wanted Sometimes it is, sometimes it isn't. Some exceptions should crash your program (runtime exceptions), others should be handled (checked exceptions). Languages that take correctness seriously should offer you both options.
- Retra 11y agoI'm not talking about handling the error, I'm talking about boilerplate. In order to get the program to even crash on error, I had to handle 4 different kinds of exceptions. I'm as much a fan of expciciteness as anyone, but there's a difference between explicit and verbose. And there's a lot to be said for constructs that don't force you to indent your code every time you call a function. My goal wasn't to write correct code, it was to test something out. To get comfortable with the library and the task. Checked exceptions get in the way of that. >Languages that take correctness seriously should offer you both options. Rust and Haskell take correctness seriously and offer neither. Checked exceptions make perfect sense in terms of ensuring correctness, but they are awful for usability and they are not the only way to achieve correctness. >Some exceptions should crash your program (runtime exceptions), others should be handled (checked exceptions). Shouldn't the user determine that, not the implementor? Why should any exceptions not be checked?
- incepted 11y agoBut you have to write the `catch` (or a `throws`). That's the point. Now if you choose to handle this stupidly, that's entirely your fault, but at least the compiler did its jobs by forcing you to think about the error case. In Go, the compiler doesn't enforce anything.
- ngrilly 11y agoHow many lines of Go have you written before writing this? In Go, as in Java with checked exceptions, the compiler forces the programmer to handle the error. Using _ in Go is not idiomatic. It's the exact equivalent of using a try/catch block with nothing in the catch block in Java.
- Karunamon 11y agoOr not checking for the exception at all. Certain classes of errors can and should be allowed to pass up the call stack and cause your program to die (something strange that I wasn't expecting and don't know how to handle happened, and now I'm in a bad state - safer to exit)
- pcwalton 11y agoIf you call a function that returns nothing but an error, Go does not force you to acknowledge the error's existence and will silently allow you to drop it.
- howeyc 11y ago> Checked exceptions don't let you get away with this kind of sloppy programming. They sure do. Just write your Java code without a try/catch block anywhere, or just have your catch do absolutely nothing. You can do it, trust me. Exceptions don't stop programmers from doing anything.
- Chris_Newton 11y agoJust write your Java code without a try/catch block anywhere The point of checked exceptions is that you can’t do that. It is a compile-time error to not either catch the exception or explicitly indicate that you will propagate it. Unfortunately, at least in Java, that style proved too onerous for a lot of programmers and motivated the catch-all, do-nothing wrapper idiom that is completely unhelpful as far as safety goes. Exceptions don't stop programmers from doing anything. At least in principle, you can statically detect any failures to handle possible exceptions if you have a suitable type system. Of course, if you just hack around those warnings, as we’ve seen Java programmers do with checked exceptions and catch-alls, then you’re no better off than if you ignored a relevant return code in the first place (aside, perhaps, from making it much more obvious to a static analyser or during a code review that you are doing so).
- AnimalMuppet 11y ago> > Just write your Java code without a try/catch block anywhere > The point of checked exceptions is that you can’t do that. Sure you can. You just have to write "throws Exception" after all your function signatures.
- Chris_Newton 11y agoThat would be a (perhaps rather foolish) variation of the “explicitly indicate that you will propagate it” case.
- incepted 11y ago> Just write your Java code without a try/catch block anywhere You can't. I don't think you understand how checked exceptions work.
- jfb 11y agoYou've never seen the Java "pattern" of try { foo(); } catch (Exception e) { ; } ?
- mcguire 11y agoThis is not idiomatic Java code and in my experience not many competent people will do this. New Java programmers who ask for help with a piece of code that ignores the error are told immediately to check the error. And experienced Java programmers simply do not ignore the error. Also, you don't need the semicolon.
- jfb 11y agoIt's not idiomatic, or good, but neither is ignoring the return value from a go function call. Both languages fail to provide better affordances for error checking.
- mcguire 11y agoThat it's bad style is kind of the point: The standard response from Go advocates is that ignoring errors is not idiomatic, but it's not good style anywhere, in any language where it isn't outright illegal.
- jfb 11y agoI think we're in violent agreement. I wasn't saying that Go's affordances solve this problem, merely pointing out that checked exceptions in Java aren't any kind of a dispositive solution.
- deleted 11y ago[deleted]
- shawnps 11y agoThis is not idiomatic Go code and in my experience not many people will do this. New Go programmers who ask for help with a piece of code that ignores the error are told immediately to check the error. And experienced Go programmers simply do not ignore the error.
- glittershark 11y agoEven beyond that is: var foo *bar foo.Baz() Accidentally dereferencing a null pointer in Go is dangerously easy
- throwa990323249 11y agoActually that doesn't dereference a nil. https://play.golang.org/p/cjmflMBhF7 https://play.golang.org/p/cjmflMBhF7 Why not learn the language before criticizing it?
- kornish 11y agoTo be fair, we don't know if `Baz` is a pointer or value receiver in the parent example. So it could: https://play.golang.org/p/fYO8jBbVQ5 https://play.golang.org/p/fYO8jBbVQ5
- mratzloff 11y agoThat's true, but it's pretty uncommon for a function to receive a value, and if so you either have a good reason for it or you're doing something wrong.
- whateveracct 11y agoYou created a playground that intentionally avoids the nil ptr dereference. https://play.golang.org/p/Cu4sE829ZZ https://play.golang.org/p/Cu4sE829ZZ
- jerf 11y agoYou can actually create meaningful implementations of methods on nil pointers. if b == nil { fmt.Println(":)") } else { fmt.Println(b.emote) } In this case, that's useless, but that's an artifact of the chosen example. I use it every so often in places where it happens to have meaning. Go often treats nil as a legal value, which means that some of the things you might expect to crash don't, and when used idiomatically can sometimes make for shorter code. For instance, the "length" call on slices will happily take a nil and return 0, you can "append" to a nil slice and get a slice back, etc. Ultimately it's still a language with a null in it, though. There's no non-nil pointer type.
- Nexialist 11y agoAlthough a lot of people are pointing out (correctly) that it's trivially easy to ignore a checked exception, it does at least do two things: 1. Signal to the calling programmer that some error condition can occur. For example having to catch SomethingNotFound tells them that it's possible that Something might not be found. 2. You just put in your coding standards that you must do something sensible inside of a catch block, and get a code checker to break the build. I don't think anybody is trying to say that checked exceptions have "solved" the problem of people ignoring error conditions. It does at least give you an easily visible thing to point at and say "that's wrong" though.
- jerf 11y agoI've got a blog post on deck that basically says that just as Joel on Software proposed that the vast bulk of the advantage of scripting languages in the 2000s was garbage collection, I propose that the big advancement in error handling lately is simply the idea that it ought to be stuck in the programmer's face, and the exact manner in which it does so isn't really very important. By that standard, exceptions actually fit in between C-style obliviousness and explicit error returns. They do allow a certain amount of implicitness (does this code have no try/catch exception handlers because the programmer is deliberately invoking the default exception behavior, or is it because they didn't think about errors at all?), but you still can't ignore errors the way you can in C. And then with explicit error returns, you can't ignore them at all without leaving a trail of your decision to do so right there in the source code. Checked exceptions tried to straddle the boundary, but I think I have to agree with the general consensus that they are a failed experiment. One of my "cut through the noise" metrics for language design decisions is "do any subsequent languages pick up the feature?". If a language as dominant as Java has a feature, but after 10-15 years no new languages are picking up the feature, that Means Something.
- mahyarm 11y agoI like how Swift does it. There are no real exceptions, but error object handling to jump to the end is fairly easy. It reduces boilerplate and increases readability. do { try error-return-statement statement statement try error-return-statement } catch ErrorType1 { ... } catch ErrorType2 { ... } It looks like exceptions, but under the hood error objects are being returned by error-return-statements, thus the explicit try keywords before them. It retains go error object simplicity, but keeps things readable and tidy.
- elcct 11y agoI don't think it is common, unless you work with pretty bad code base. You simply don't ignore errors like that.
- pcwalton 11y agoThis is not a good example of how Go makes it easy to ignore errors (which it does in some cases, but not in that way). You had to acknowledge the dropped error syntactically.
- jamwt 11y agoA better example is the timeless: err := f1() if err != nil {..} // have to do this or compiler error err = f2() // oops, forgot to actually do anything about it! Now, granted, `go vet` helps with this, but.. these kinds of things can be solved by the language proper in much better ways, and they should be type errors. Like rust's `Result` or Haskell's `Either`. Edit: rust's result is especially nice with #[must_use]. This has saved my team from mistakes relatively frequently.