What do you miss in Go and its ecosystem?

Could be anything: language tweaks, tools you miss out-of-the-box, libraries you’d like to see in std / github, all kinds of stuff, in your opinion, should be considered implementing.

Please avoid: generics, exceptions, pattern-matching and other well-discussed topic alike.

3 Likes

I don’t really miss generics or exceptions. The only thing I miss is a way to define a constant reference like “let” in other languages.

Woopaaa, we’ve got a Rust fan here! Tell me if I am mistaken.

This can be a long story… :smile:
I miss a good debugger and a gui toolkit.

10 Likes

Don’t you dare! Just use for loops! Gui toolkit is being developed atm IIRC, https://github.com/golang/exp/tree/master/shiny

Existing gui toolkits are some abandoned, some are too young to be used in production.For the moment, i use web apps running in Chrome app mode :wink:

Having let db *sql.DB as a global (where it works like ES6’s let) would cut traffic to the go StackOverflow tag in half :wink:

Serious answer: there’s a thread on the golang-dev list that includes a number of suggestions for “finishing” the standard library - Redirecting to Google Groups

I wouldn’t mind union types but it’s easy to make suggestions when you’re naive about the implementation details/overhead.

  1. var and let are good idea. It is for example in Swift

  2. some more funcionality for slices. For example remove. But it is not so important.

  3. Why is possible to have the same name for variable in block ??

func main() {
	a := 1
	if a == 1 {
		a := 2
		fmt.Println(a)
	}
	fmt.Println(a)
}
2 Likes

it is possible that a variable have the same name in a function more than once but in different blocks. in the same block is not possible. basically, any new variable become local variable in the current block.

func main() {
a := 1
if a == 1 {
	a := 2
	if a == 2 {
		a := 3
		fmt.Println(a)
	}
	fmt.Println(a)
}
fmt.Println(a)

}

This is area where programmer is able create a simple error. Instead of a:=2 she writes a=2. In another areas is golang more rigorous (is not possible declare variable and do not use it etc…).

Something to reduce error handling boilerplate. I write this too much:

if (err!=nil) {
    return err;
}

Don’t really have any suggestion. I just don’t seem to always benefit from the logic that “you have to handle the error where it happened”. For example, in a rest service I would return a “validation error” from a function 2-3 levels down the call stack, and need to bubble it up to the common handler where it would be transformed into “bad request” and returned as service result.

E.g. instead of one-liner (as would be in exception based solution) this is a piece of code on it’s own:

err = this.EnsurePermission(req,nil,permissions.CreateProject)
if err!=nil {
   return err
}

This is not a debate about exceptions. I perfectly understand the reasoning why Go does not have them. But the “if err, return nil,err” construct is something I can’t get over in Go. Don’t even know what the correct approach would be. A special language construct (like _ for “nothing here”) to forward the non-null return?

// would be equivalent of 
// result,err := resultOrError(); 
// if (err) {
//    return err
// }
result, < = resultOrError()
3 Likes

indeed, many complain about errors handling mechanism but look over Rob Pike’s article about why and how you can handle the errors.

1 Like

Yeah, that is what pisses me off so hard. Go is being pedantic on minor rubbish, like unused imports, but allows pretty ambiguous variable shadowing, which often leads to non-trivial errors (debugged one yesterday in under 10 mins, thanks to gometalinter). Maybe I am just a horrible engineer, but this doesn’t make any sense to me.

Your arguments are absolutely valid and I can put a sign under every single word. In fact, I absy love your idea of “forward non-nil return”, I think we should consider smth like this for Go2.

I just thought how what @Viktoras_Makauskas suggested could be implemented, take a look:

// How it's done today
lmao, err := Do()
if err != nil {
    return err
}

// My wet Go2 dreams...
lmao, ~ = Do()
// And that's it.

Tilde on the left hand basically says “return nil if rhand return tuple contains non-nil err and default values for other return values, otherwise keep going”. I am still not sure how this should behave in main(), looks like it mustn’t be used in main() or init(), since the main idea is to forward the non-nil err up without any real error handling (like it’s done most of the time, admit it). It looks pretty clear, yet unusual to me.

Adding a tilde to spec would be trivial and quite functional — we could think of other potential applications of it. Unfortunately, this is only a dream, since Go team won’t even consider adding such a “crazy” thing. Remember Pike’s just use for loops (which is reasonable).

The “Done today” example is bad practice, you should absolutely take the chance to add more information to the error if it is available to you using fmt.Errorf

2 Likes

In fact, besides the fact that “done today” is a bad practice, it is also a commonly accepted error handling flow, which you can find everywhere. I can’t imagine people being pedantic with fmt.Errorf on every single error (marshalling? os.Open? etc), only for majors. If you don’t believe me, do a grep/sift on some popular golang projects, like syncthing or docker with if err != nil{\n\treturn err;\n}.

I will fmt.Errorf almost every single one of my errors, the fact it’s largely done wrong today is absolutely not a good reason to encourage doing it even more wrong by making it a language construct.

2 Likes

If by “largely” you mean “generally accepted”, than yes. Take a look at standard library, it’s done everywhere.

@tucnak, I feel like I have seen a proposal just like this on golang-nuts, and the result was that the proposer couldn’t describe a complete solution for how it should work. It was full of ambiguity in how it would work under different circumstances…

  1. What does the ~ usage do if the thing being called does not return an error?
  2. What happens if the thing being called returns multiple errors? Which one gets returned automatically?
  3. If the current function doesn’t return an error type, what happens when you use the ~ on a function call? And what if the current function returns multiple errors. Which one is filled?

Basically it seems, to me (and from having followed discussions of stuff like this before), too magical to work in a way which is clear in all cases.

3 Likes