DEV Community

Cover image for My Favorite Go 2 Proposals
Dean Bassett
Dean Bassett

Posted on

My Favorite Go 2 Proposals

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!

Discussion (23)

Collapse
agrim profile image
Agrim Prasad

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 of try-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)

Collapse
dean profile image
Dean Bassett Author

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 including github.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)

Collapse
okolbay profile image
andrew • Edited on

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.

Collapse
dean profile image
Dean Bassett Author

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.

Collapse
okolbay profile image
andrew • Edited on

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

Thread Thread
dean profile image
Dean Bassett Author

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

Collapse
davidmz profile image
Давид Мзареулян

Your code reminded me of my old library, mustbe. With mustbe, the code looks like this:

func SomeBigFunctionWithCollect() (i int, err error) {
  defer mustbe.Catched(func(e error) {
    fmt.Println("Error in SomeBigFunction:", e)
    err = e
  })

  mustbe.OK(SomeErrorProneFunction())
  mustbe.OKVal(AnotherFunc())
  // ...

  i = mustbe.OKVal(LastFunc()).(int)

  return
}

It's a bit more verbose, but it works already in Go1. Under the hood it uses panics, of course.

Collapse
vkuznecovas profile image
Viktoras

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.

Collapse
dean profile image
Dean Bassett Author

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 the if 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.

Collapse
telecoda profile image
Rob Baines

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

Collapse
dean profile image
Dean Bassett Author

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)

Collapse
kayis profile image
K (he/him)

Go finally gets generics?!

Collapse
dean profile image
Dean Bassett Author

Not necessarily! Remember that all of these are just proposals.

Collapse
dean profile image
Dean Bassett Author

I like that syntax, although my main issue is how it would treat multiple select statements. I had mentioned using err! instead of err. Maybe even err^ since it's moving "up" to the collect statement. Syntax isn't a huge issue and can always be figured out after semantics though :)

Collapse
l0k1_smiren profile image
((( лoки )))

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.

Collapse
nanohard profile image
William Antonelli

I like the idea of collect, but the readability takes a nose-dive with that weird underscore syntax; I like the idea of err!.

Collapse
dean profile image
Dean Bassett Author

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

Collapse
nanohard profile image
William Antonelli

Oh yeah, that's way better.

Collapse
mikeschinkel profile image
Mike Schinkel

Nice.

That said, I don't love the added syntax of #2. I proposed a simplified alternative here though:

github.com/golang/go/issues/25626#...