Please create an account to participate in the Slashdot moderation system

 



Forgot your password?
typodupeerror
×
Programming

Go 1.15 Planning Will Not 'Try' Error Handling (golang.org) 40

The Go team is planning for a February release of Go 1.14, and "Per the process outlined in the Go 2, here we come! blog post, it is again the time in our development and release cycle to consider if and what language or library changes we might want to include for our next release, Go 1.15, scheduled for August of this year."
The primary goals for Go remain package and version management, better error handling support, and generics. Module support is in good shape and getting better with each day, and we are also making progress on the generics front (more on that later this year).

Our attempt seven months ago at providing a better error handling mechanism, the try proposal, met good support but also strong opposition and we decided to abandon it. In its aftermath there were many follow-up proposals, but none of them seemed convincing enough, clearly superior to the try proposal, or less likely to cause similar controversy. Thus, we have not further pursued changes to error handling for now. Perhaps some future insight will help us to improve upon the status quo.

Given that modules and generics are actively being worked on, and with error handling changes out of the way for the time being, what other changes should we pursue, if any? There are some perennial favorites such as requests for enums and immutable types, but none of those ideas are sufficiently developed yet, nor are they urgent enough to warrant a lot of attention by the Go team, especially when also considering the cost of making a language change.

After reviewing all potentially viable proposals, and more importantly, because we don't want to incrementally add new features without a long-term plan, we concluded that it is better to hold off with major changes this time. Instead we concentrate on a couple of new vet checks and a minor adjustment to the language...

We believe that none of these three proposals are controversial but there's always a chance that we missed something important. For that reason we plan to have the proposals implemented at the beginning of the Go 1.15 release cycle (at or shortly after the Go 1.14 release) so that there is plenty of time to gather experience and provide feedback. Per the proposal evaluation process, the final decision will be made at the end of the development cycle, at the beginning of May, 2020.

This discussion has been archived. No new comments can be posted.

Go 1.15 Planning Will Not 'Try' Error Handling

Comments Filter:
  • Compiles fast, simple syntax. Tens years from now it will be the next C++.

    • Go is part of Plan 9 that somehow managed to escape permanent erasure. The assembler appears to be based on the Plan 9 assembler which is cutting-edge... for 1979. It can't even statically link parts of a library without including the entire library. This is why Go executables are all greater than a megabyte.

      Go may have potential but if will continue to be weighed down until they overhaul the compiler and write a formal specification.

      • Except the compiler is already being overhauled. And as for binary size, I'm not sure if you're attributing the reasons for it correctly. Full reflective and debugging information in binaries is generally considered being the major contributor to Go's binary size. And you kind of can't have reflective calls AND erase code in advance because you don't know if erased code won't get called reflectively. C doesn't have this problem since it's not reflective.
      • It can't even statically link parts of a library without including the entire library. This is why Go executables are all greater than a megabyte.

        If a megabyte bothers you, then never look in your node_modules directory.

    • by Junta ( 36770 )

      My experience with go has been largely positive.

      I think the biggest drawback compared to most modern languages is returning to C-style error handling. It's incredibly tedious compared to block-level error handling.

  • by fubarrr ( 884157 )

    Go is still very much a WIP language, and >1.0 ver here disinformates people.

    Google will be dropping the ball on it imho. The have a good record terminating projects lacking early traction

  • by BAReFO0t ( 6240524 ) on Saturday February 01, 2020 @03:15PM (#59679682)

    I always found it weird, to declare some states as "errors" and just bail.
    It is just a different state. Requiring a different action. Stop treating it as special so you can slack off and write shitty code.

    Almost always, there is something you can do to get to the target state. E.g. retry (cosmic ray checksum corruption), retry with a longer delay (slow link), enable some OS/hardware feature, etc. And it is mostly insufficient resources too.
    In any case you can't resolve yourself, you can ask the OS, or the user, to do an action on your behalf. (Like, walk to a place with cell phone / wifi reception.)

    But in most cases, it isn't even a "oh noes" problem at all!
    Like when you did not find a record in a database. E.g. a web search coming up empty. It succeded in doing its job. There are zero results. That is not an error.

    If coders thought that way, software would be a LOT more stable. And secure. And users would not get stuck on stupid "errors" that don't tell them how to resolve the situation!

    • by thereitis ( 2355426 ) on Saturday February 01, 2020 @03:33PM (#59679730) Journal

      I could probably learn to live with Go error handling, but not having some way to execute code _during development_ with unused imports/variables/functions is insane. For instance, if I want to run my code with a single line commented out could result in a variable becoming unused (error), import unused (error), function unused (error), so now I'm left with doing a bunch of leg work that will have to be undone later, just so I can try a simple change. I don't know how people can tolerate working with such a language.

      • I tend to disagree with Go's philosophy of "there's no such thing as a compiler warning". In other languages, I'm disciplined enough to never check in code that has any warnings at all, but I guess the Go team decided that we can't have nice things because of undisciplined developers.

        I found that in practice, the imports issue is the worst. That can be addressed by having your editor run the "goimports" utility as an autocommand on file save, and it automagically finds and updates most imports for you, so y

        • In other languages, I'm disciplined enough to never check in code that has any warnings at all, but I guess the Go team decided that we can't have nice things because of undisciplined developers.

          Personal repos, sure, but at work don't you have some checks that run before merging to master? You don't need discipline if code has to compile without warnings and run unit and regression tests.

    • "It looks like you were trying to divide by zero, would you like some help with that"

    • by swilver ( 617741 ) on Saturday February 01, 2020 @03:59PM (#59679786)

      Good code uses short functions. If every function needs to deal with errors, the result is that people will write bigger functions instead, resulting in bad code.

      You could try handling every error at every level, but you may not even know how to handle an error in a piece of code nested more than 2 or 3 times. Was it called as part of a batch? As part of a request? On a background thread? The called code doesn't know.

      So you pass the error up (the smart people do that anyway), the stupid people will assume it is part of specific calling code and handle the error at the wrong level (like doing a slow retry, but maybe the calling code wants to fall back on a cached value instead as that is "good enough" for the specific case).

      Passing errors up is ideal with exceptions, as the number of layers in between the code that generated the error and the code that initiated it doesn't matter, leaving you free to do proper design and separation of responsibilities. If however every layer means adding another piece of error handling logic, people will think twice and write shitty code instead.

      • You could try handling every error at every level, but you may not even know how to handle an error in a piece of code nested more than 2 or 3 times. Was it called as part of a batch? As part of a request? On a background thread? The called code doesn't know.

        Sounds like the reason for why Common Lisp conditions with restarts were invented.

        • It's funny, DOS also supported this kind of thing (remember "abort, retry, ignore"? that was the retry). Weird how people forget things (and then reinvent them with a new buzzword).

      • by xonen ( 774419 )

        [...]code nested more than 2 or 3 times. Was it called as part of a batch? As part of a request? On a background thread? The called code doesn't know.

        Nor should it need to know. It needs to deal with whatever stuff it's calling itself and dependent on, and fail gracefully when it can't.

        The thing with exceptions is, you may catch it but still don't know what caused the issue, well you could backtrace it etc but that's even more hassle defeating the purpose of 'simpler code', and you potentially have memory leaks, half-open handles, inconsistent data structures and dangling pointers on the fly as side-effects.

        Exceptions are great if there's a user to catch

        • I think people miss some of the history.

          Once upon a time, only BASIC and Assembly language had anything resembling exceptions (on error goto/gosub/resume/resume next in basic, and interrupts in asm) and then somehow, even though BASIC was hated and assembly was hard, this event based atrocity became acceptable in the form of try/catch.

          What we need is an 'exception handing in considered harmful' push, because even though it has a facade of structured programming, its really spaghetti.
    • Almost always, there is something you can do to get to the target state.

      Bill Gates already knew this 40 years ago.

      There are always three ways out of a problem situation: "Abort, Retry, Ignore?"

    • Re: (Score:2, Insightful)

      by caseih ( 160668 )

      Code that cannot explicitly deal with certain states should absolutely bail out. There's no other sane option, other than to throw the end user into a debugger.

      I never could quite figure out what to do with exceptions in C++, especially since there was a lot of non-exception error-handling baggage from C land. And then how do I know what I need to catch? Do I overload my code with custom exception classes I can throw for every little error? This is likely why people were so opposed to exception handling

      • Code that cannot explicitly deal with certain states should absolutely bail out. There's no other sane option, other than to throw the end user into a debugger.

        I never could quite figure out what to do with exceptions in C++, especially since there was a lot of non-exception error-handling baggage from C land. And then how do I know what I need to catch? Do I overload my code with custom exception classes I can throw for every little error? This is likely why people were so opposed to exception handling being proposed for Go. It seems like a mess, right?

        But then I started programming in Python and exception handling has become a lot clearer, cleaner, and much less error-prone, if you'll pardon the pun. An exception is, by definition, exceptional: it's not a normal thing. Thus if something exceptional happens that you aren't equipped to deal with, don't catch it. Let it bubble up to the caller who will it if it can, or if not, absolutely crash the program with a trace back. This might sound extreme, but it's very logical. If no function is equipped to deal with the exception, then there's no sane option but to bail out. A program that doesn't know what to do about common disk errors, for example, shouldn't just carry on as if nothing is wrong. Silent failure is worse than crashing. If a program doesn't know how to resolve an error, I don't see what you think it should do.

        So in Python, the general rule is to not catch exceptions, unless you are specifically writing code to deal with certain exceptions (a file that's not found, for example). You can't possibly code for all contingencies, nor does it make sense to try.

        Raising exceptions is common, but done judiciously. If a bug is the original cause of the exception, one should not catch it and then raise some arbitrary third-party exception. Let the original exception stand for debugging purposes. Be careful and judicious in the custom exceptions your code does choose to raise.

        All in all, it's a very productive and logical way of doing exception handling, and if more languages did that, there'd be much less resistance to exceptions because they would make more sense. And software would be more stable and more secure. With this sort of background, I have a hard time understanding (remembering) the resistance to exception handling.

        The exceptions in C++ work exactly the same way as in python. You generaly don't want to try/catch most of them.

  • Honest question here.
    I've browsed through the "kerfuffle" discussions at the time, and almost no one were even considering try..catch. I failed in recognize why, it seemed like almost a taboo...
    I really like Golang, but the poor error handling really stopped me from using it in bigger projects. Too much replicated code (and therefore, effort) would go on error handling.
    In my opinion, the try() solution would be half baked. Some code would be reused, but one would still have to encapsulate with try() every d

    • by swilver ( 617741 )

      They didn't invent it, or it is isn't different enough -- no doubt even suggesting it will mean you'll never be taken serious in the "go" space again.

    • by skoskav ( 1551805 ) on Saturday February 01, 2020 @04:16PM (#59679822)

      The designer of Go has a proverb that errors are values [youtube.com]. I assume this is why errors have to be handled per-call with the return tuple and won't affect a function's signature, compared to try-catch which works per-block and may affect a function's signature.

      As someone who works with both Java and Go, I find that both approaches can be used both well and terribly. Go functions can contain a lot of duplicated error-checking blocks, that I wish there was some clever syntactical sugar for:

      if err != nil {
      return fmt.Errorf(..., err)
      }

      Bad Java code on the other hand can contain a lot of optionally caught RuntimeExceptions (or its subclasses) that are used for control flow, which hampers refactoring; as well as uninformatively broad Exceptions thrown because some developer was too lazy to create their own Exception subclass.

  • ... the try proposal, met good support but also strong opposition and we decided to abandon it.

    He was heard remarking, "Do or do dot, there is no try."

  • It's another example of a crap language either be made or supported by Google. Why do they suck so much at creating or choosing languages? Java on phone..ugh. On the browser they made javascript the defacto standard (because Dart was also trash) by optimizing chrome accordingly.

    Apple, on the other hand, after their objective C debacle, at least introduced Swift.

    • Apple, on the other hand, after their objective C debacle, at least introduced Swift.

      In fairness, Apple inherited Objective-C from NeXT as the implementation language for what would become MacOS/X. At the time, Apple didn't have the luxury of developing a whole new language since surviving was their main goal.

      From my cursory perusals of Swift, it seems fine, and cleaner, but there's really nothing special about the language. It brings nothing new to the table of programming languages. At least Go offers

      • by w1z7ard ( 227376 )

        At least Go offers channels and go-routines that are pretty nifty. OTOH, Go has a bizarre inheritance model.

        Do you find yourself missing Go channels and subroutines when using other languages? Curious...

        • Do you find yourself missing Go channels and subroutines when using other languages? Curious...

          Not really, but that's because I haven't done a lot of programming in Go since my day job isn't in Go. When using the languages I do use daily, I don't really think about missing channels because I'm thinking in the language I'm using that doesn't have them.

  • ... that the authors have their eye on the future. Just started my first go project some months ago, and from what I've seen, it's got a long way to go. Though it IS awesome to see my API serving reqeusts the moment I take my finger off Enter on the exe - that's just too neat to not love :)
  • Golang made the weird decision to support a few generic types (dict and list) but to prevent people from writing their own generic functions. This makes generic support in golang worse than any language. In old Java you could at least be sure that everything is a list or map of object, so you could write a generic function with shitty type checking. In go even that is not impossible, so people end up writing the same function again and again, or using reflection in ways it was not meant to be used, or appl

  • by DrXym ( 126579 ) on Sunday February 02, 2020 @06:16AM (#59681150)
    Go's error handling is very slapdash - a function that can fail will return an error, or it returns a tuple - (result, error). Where "error" is a built-in type. In the tuple case the value is only valid if error is nil and the caller is supposed to test if error is non-nil. But the caller doesn't have to. And the function still has to return something for the result even when there is an error which is just dumb. It makes for a mess of code.

    And the error imparts no meaning on what the error was. You can print it out as a string, but if you have code that actually needs to see the error, the generic error must be cast into the explicit type to get at the value. It's very clumsy.

    Other recent languages like Swift and Rust have far better and formal ways of propagating errors up the call chain. Swift has a throws/try/catch for errors (not exceptions) and Rust has an explicit Result generic for functions that return values or errors. Not only do they make it more difficult for code to forget to handle errors, they also make it easier to test the error if one happens.

    It seems incredible that Go would keep putting this off.

    • by LiENUS ( 207736 )

      And the error imparts no meaning on what the error was. You can print it out as a string, but if you have code that actually needs to see the error, the generic error must be cast into the explicit type to get at the value. It's very clumsy.

      This was improved as of golang 1.13 with is and as.

"...a most excellent barbarian ... Genghis Kahn!" -- _Bill And Ted's Excellent Adventure_

Working...