As some gophers may have heard, Go 2 may be coming soon! It's still in the planning phase though, and the Go team is still working on what features should and shouldn't be in the language.
One of my favorite things about Go is its lack of syntactic sugar, it really feels like I'm problem solving, rather than writing tons of gibberish. The Go team doesn't want to have yet another feature-bloated language, which is why I really enjoy it.
Anyway, there's over 7 pages of Go 2 proposals, and I've been searching through them, so I thought I'd list some of my favorites.
Interface Literals #25860
This one is a bit hard to understand at first, but once you understand it, it becomes much simpler to read.
So let's say you want to sort a slice of strings... This is now simplified with sort.Strings
and sort.Slice
, but for the sake of example, let's pretend sort.Sort
is all we're able to use. This function takes an interface (called sort.Interface
) which has 3 methods defined, so in order to use it, you must make sure those 3 methods are defined for your type:
But with this proposal, we can make it look like this instead!
Essentially what we have done is to use an interface literal instead of needing to make a new type! This means that the code that you use to sort can now be put where you actually do your sorting.
Add collect
statements to the language #25626
This one is really nice, actually. They want to add a statement called collect
to the language. It's hard to explain with words (in my opinion), so let's do it with an example!
Here is some valid Go code, with some error handling of course:
And as my Computer Science professor said, if you're repeating code, you're doing it wrong! But in Go, there's no good way to really handle the err != nil
repetition problem here, so how could we help this? The collect
statement helps fix this issue!
So let's have the same code, but with the collect
statement.
So what does this do? Well the collect err
indicates that we are going to collect into a variable err
. Then, each time we assign to _!
, it assigns that value to err
, and checks if err != nil
. If the assigned value is not nil, it exits the collect
statement, and then the error handling can be done afterward.
My main issue with the proposal is that the syntax is a bit confusing (I personally don't like the _!
syntax, I made a suggestion to use err!
instead, which makes it a bit more clear).
Fix casing issues #1187
This one is quite a bit simpler than the last one. The os
package has a lot of confusing casing, it's not always clear if the correct function call is os.Chdir
or os.ChDir
, or if it should be os.Tempdir
or os.TempDir
. I'm hoping the proposal to fix these casing issues gets accepted!
There are TONS of Go 2 proposals. Go has some really strong views on what should/shouldn't be in the language, the Go creators definitely don't want to make another C#, JavaScript, or other feature-bloated language. While I really like the idea of a collect
statement, I'm not sure if the Go creators would like it, as it may be seen as an unnecessary feature (which I understand).
What do you think about the proposals? Do you have any you want to add? Let me know, Go is one of my favorite languages out there, and I'd love to have more insight as to what its future may look like!
Top comments (19)
Nice little collection you've got there. I agree that the casing issues should be fixed, although this shouldn't be a high priority since you can always set up your editor to auto-complete this stuff for you.
I'm
meh
about interface literals to be honest. Making the sorter a separate type makes it more re-usable in my opinion.The
collect
statement is sort oftry-catch
again, isn't it? The problem with these kind of catch-all statements is that developers end up writing hundreds of lines of code in the block, and then you are left wondering about where exactly the error was encountered (especially when using error tracking software such as Rollbar or Sentry)I really like the idea of interface literals, mainly for the reason that it groups code where it gets executed. It is nice to force re-usability though.
I agree with the critique on
collect
though, and I personally don't think it's going to go through. I know a lot of people are unhappy with Go's error handling for several reasons though, so I personally think it may be a step in the right direction, although I'm more of a fan of includinggithub.com/pkg/errors
into the standard library, which is a separate proposal. (I didn't include it in here since I believe it could instead just be added in Go 1)Then, each time we assign to _!, it assigns that value to err, and checks if err != nil. If the assigned value is not nil, it exits the collect statement, and then the error handling can be done afterward.
...
...
...
congratulations, you just invented try-catch, which is a goto in disguise. truly everything new is old )
when I was inspired by golang (and node I guess)and wanted to do go-like error handling in php, I proposed to add conventional first argument, passed by reference to accumulate errors
after few functions called one can check if any errors occured and then decide what to return from calling function (maybe propagate errors further up the stack)
it was, of course, more of experiment than a complete solution, but it gave an alternative view on exceptions. Exceptions are gotos:
if first function in try block throws, you magically avoid calling second function which is, very likely, acceps value returned by first one as input. So exceptions are making your code obscure and extremely hard to understand. Actually, control on what happens in calling function is now in called function - just throw there and you force client code to obey and go to catch block, even though client code might wanted to do some more calls. Oh you really want to make sure you do that? Welcome to try-with-resources and finally and all sort of even more obscure stuff )
Instead it would be logical to admit that every time you call a function that would otherwise throw, you should really check error returned from this function and then branch your control flow with if statement - this way calling function is back in charge of what is going on. As a result code will look ugly in most of the languages. How to solve this - Im not sure yet, Optionals in java seems to be my next wearpon of choice - most of methods I write are now a chain of Optional.ifPresentOrElse() calls. Pretty declarative, I like to think of myself as a developer who uses functional style, who doesnt?))
Im still in search for THE solution (Im looking at you, monads), but my point here - question everything until you got to the core. Dont run around in circles.
While it's similar to try-catch,
collect
is a lot more explicit as to what is going on. I'll admit that it's the least favorite of the 3 I showed, though.can you elaborate on how it is more explicit? it is really stopping execution of collected code block and jumps to if err != nil block?
edit:
looks like it is,
Whenever _! is assigned to, an implicit nil check is performed, and if _! is not nil, the block ceases execution.
from original proposal desription
doesnt look differrnt from throw-catch like semantics of other languages
When I say it's more explicit, I mean that in a typical try-catch, there's absolutely no indication as to where the error came from. This at least shows which places the error could have came from. Again, it's not my favorite thing in the world, but I'm not entirely against it
Your code reminded me of my old library, mustbe. With mustbe, the code looks like this:
It's a bit more verbose, but it works already in Go1. Under the hood it uses panics, of course.
Not a fan of the
collect
statement either.The point of handling different errors is that you often have to do different things based upon where the code errors.
Bundling them into a single return delegates the responsibility (and understanding) to somewhere or someone else
Something I might want to add:
proposal: Go 2: add become statement to support tail calls #22624
Tail calls allow for much faster recursion at the cost of reduced debug-ability. Might make a second post with some others that I may have missed! (Generics, other error handling solutions, etc)
Go finally gets generics?!
Not necessarily! Remember that all of these are just proposals.
I like that syntax, although my main issue is how it would treat multiple
select
statements. I had mentioned usingerr!
instead oferr
. Maybe evenerr^
since it's moving "up" to the collect statement. Syntax isn't a huge issue and can always be figured out after semantics though :)I'm a fan of fixing the casing issues, but not too big of a fan of the other two. Mainly because it feels like those two proposals add syntactic sugar in order to achieve brevity. I do believe verbosity is one of the reasons I like Go so much. You spend most of the day thinking, not writing code. Making it easier to read and understand is a plus for me. Having more constructs does add to more confusion while reading IMHO.
I totally agree with verbosity being important in Go. I think the
collect
is my least favorite of the three, I personally don't mind theif err != nil
pattern that much. I like the idea of interface literals though, I feel like needing my code to be separate from where I use it is a bit much.More consistency in the stdlib will be very welcome, but really this is not per se Go 2.
I don't like the collect. Right now, using a special function, you can handle all error cases except for when you need to break out of a block or function. A label, which nobody uses, could be used in a closure to skip to the end, but it is ugly. If there was a function to jump back two steps in the stack rather than just one and you have your tidy, structured and most importantly, short error handler. Collect doesn't even address this and if you didn't know you can make one line error handlers already except that trigger a break... A collect statement is far less obvious than
breakon(err)
or so, and a full handler function can also be written, and it could be completely up to you how to handle it.Personally, apart from mandatory system specific, 'difficult' to write from scratch algorithms, I often don't even use stdlib that much.
If there was one thing I would like, that would be the option of curly blocks or whitespace delimited a la python. Just look at a typical function in Go. The opening parenthesis distracts (from human scripts we more usually use a : to head a subsection, like Modula and Oberon and go switches)... And then gofmt leaves the closure parenthesis on an otherwise empty line. Gofmt almost already forces the correct indentation anyway (it only allows open and close parentheses on closures very short if blocks).
Other than that, I would like a more concise but unambiguous closure, though on a github issue I posted, someone pointed out the increased ambiguity.
Personally, I will be disappointed if any changes that make the version two are not profoundly powerful, like for statements and strict static typing and interfaces combined.
I like the idea of
collect
, but the readability takes a nose-dive with that weird underscore syntax; I like the idea oferr!
.There's a new error handling proposal out there that's receiving a lot of criticism. I'll probably make a post about it soon
Oh yeah, that's way better.