Go has some really great features, I've written a few thousand lines in it and enjoyed it, but there are some strange hangups that the go designers have that in the end make me think its going to go nowhere.
1. Rob Pike is immensely proud that the language has no generics, but this means that in the last 2 years, there isnt a proper implementation of a linked list that can hold an arbitrary type, or a min-heap, an ordered map, or a b-tree, or any one of countless data structures that one can take for granted in every other language. And yes, there are implementations that take interfaces, but you have to very odd-looking casts to coerce values in and out of them.
2. Go - or its testing support - doesnt allow a simple assert or EQUALS macro, simply because Rob believes everything should be done with if/then structures. Along with error handling, this makes go tests painful to read.
3. Idiosyncratic handling of pointers and values, leading to confusion everywhere and accidental copies and bugs where people pass by value accidentally because its extremely easy to.
4. Channels aren't really that useful beyond small programs (IMHO, maybe I'm wrong), and by making them synchronous any non-trivial go concurrent program has to reason very carefully to avoid deadlocks.
There are countless similar things. People will put up with these idiosyncracies for a while but move on in the end.
1. Your characterization of Rob's position on generics is not at all accurate. The Go team's view, in a nutshell, is that generics would offer some exciting possibilities for Go (particularly when combined with its concurrency model) but that it is also extremely hard to do generics well. We have put a huge amount of work into defining and refining Go, and we don't want to break it with a bad generics implementation.
There are plenty of "proper implementations" of these collection classes. Your only criticism of them seems to be that they are not type safe. But it is trivial to implement a type safe wrapper around such containers, if you desire it. So the situation is perhaps a little cumbersome, but no worse than C. I don't think this is enough to doom the language.
2. This appears to be a matter of taste. You find Go's tests hard to read. I find them easy to read, as they're not written in some domain-specific testing language. They're just Go code.
If you need asserts in your Go tests, they're trivial to add with an auxiliary package, and thanks to "go get" it is trivial to install and use external packages.
3. I have carefully reviewed the code of hundreds of new Go programmers (I'm a Go readability reviewer at Google and work on the open source project) and I haven't observed the issues you describe here. I sometimes see an initial confusion about addressability, but it is usually just this: http://golang.org/doc/go_faq.html#methods_on_values_or_point...
4. I think you're wrong. Think of any time you've written an event loop or had to rally multiple threads. I'm confident that in most of those cases you could have done it more cleanly with goroutines and channels.
Finally, look at the state of programming today. Most of the languages and libraries that people use are riddled with idiosyncrasies. The Go language and libraries, by contrast, are amazingly regular. This is not just my opinion, but the feedback that I receive consistently from Go programmers around the world.
> So the situation is perhaps a little cumbersome, but no worse than C.
Actually, this is not totally true. C has pre-processor and void * which allows for simple generic data structures with no performance impact. go ties your hands here since you have to use type-assertions which are not free, unlike C casts.
> 4. I think you're wrong. Think of any time you've written an event loop or had to rally multiple threads. I'm confident that in most of those cases you could have done it more cleanly with goroutines and channels.
Goroutines are great, but synchronous channels are not at all easy to use beyond simple producer/consumer models.
I'll also note that for both complaints 1 and 2, you think its trivial for programmers to just do the work, but I though go was all about saving programmer time?
> I'll also note that for both complaints 1 and 2, you think its trivial for programmers to just do the work, but I though go was all about saving programmer time?
Go is "penny foolish and pound wise", to subvert the maxim.
It is indeed trivial for programmers to just do the work, and in return you get an amazingly regular system that saves huge swathes of time grappling with larger issues.
I've noticed this realization occurring to other programmers. It's not at all obvious until you've written a significant amount of Go code.
> The Go team's view, in a nutshell, is that generics would offer some exciting possibilities for Go (particularly when combined with its concurrency model) but that it is also extremely hard to do generics well. We have put a huge amount of work into defining and refining Go, and we don't want to break it with a bad generics implementation.
Wouldn't it have been a good idea to take generics into account from the very start?
This is one of my concerns. Java clearly suffers from having generics bolted on much later and the underlying type system would be different if generics were contemplated from the start. Will Go have similar problems when they eventually add generics?
Actually the Go team has mentioned what happened with Java is a reason why they have not added generics, they have said they wont add them unless they are 100% certain that they are happy with the design and that they will not damage the language.
>There are plenty of "proper implementations" of these collection classes. Your only criticism of them seems to be that they are not type safe. But it is trivial to implement a type safe wrapper around such containers, if you desire it. So the situation is perhaps a little cumbersome, but no worse than C.
"no worse than C" doesn't sound particularly enticing.
>The Go language and libraries, by contrast, are amazingly regular. This is not just my opinion, but the feedback that I receive consistently from Go programmers around the world.
I tend to agree about the lack of generics - the type of people who design and write standard libraries (e.g. Rob Pike and co.) may find it easy to put these things together, but they aren't representative of the general class of programmers, and there should be easy ways to make typesafe collections available to the average programmer (and making them write the same boilerplate around someone else's empty-interface using code may be mechanical, but it isn't low-effort enough to be "easy"). That said, I generally like the direction Go is taking as a language, and would like to see it succeed.
It's nice for languages to have a "benevolent dictator", but Go insists in a lot of arbitrary but not that good choices like the above.
I would add the bizarro build system (go build et al), that if you want to use you have to follow some rather silly conventions (a little flexibility would go a long way).
The GC also leaves a lot to be desired --they will implement something better eventually, but why wasn't that a top priority in 2012 for a "server systems" language? On 32 bits you are mostly toast with OOM errors, but even on 64 bit the GC is simplistic compared to most modern languages. YouTube, for example, had to jump through several hoops with memory issues to use Go in front of MySQL.
And, while the results are faster than Python/Ruby, they are not that competitive with C/C++ or even Java. The "20% slower than C" claim that you'll read is mostly BS. YMMV.
It doesn't help that if anybody brings up those issues, the general sentiment from the Go community (lists, etc) is also: "you're doing it wrong, reverse course, Go is perfect".
That said, I like Go, if it improves a bit with a 2.0 version, it can go places...
Go language has no syntactic difference between owning and non-owning pointers. Therefore, it is impossible to replace stop-the-world GC with reference counting GC eventually. IMHO that's a flaw in the language design and it's too late to fix it, this train is gone.
Nevertheless, we have other good ideas in programming language design these days. Vala, for example, has robust memory management (so it will have predictable memory use on heavily loaded web or db server), and also "async" methods and "yield" statement (borrowed from Python/C#), which effectively turns a function into a class with locals and instruction pointer converted to fields. That way, function execution can be interrupted and restarted at any moment (e.g. HTTP request handler waiting for database to respond).
Channels, coroutines and cactus stack in Go are great, but there are other worthwhile appoarches to solve C10K problem, and who knowns, maybe yield and async over traditional linear stack is better?
1. Rob Pike is immensely proud that the language has no generics, but this means that in the last 2 years, there isnt a proper implementation of a linked list that can hold an arbitrary type, or a min-heap, an ordered map, or a b-tree, or any one of countless data structures that one can take for granted in every other language. And yes, there are implementations that take interfaces, but you have to very odd-looking casts to coerce values in and out of them.
2. Go - or its testing support - doesnt allow a simple assert or EQUALS macro, simply because Rob believes everything should be done with if/then structures. Along with error handling, this makes go tests painful to read.
3. Idiosyncratic handling of pointers and values, leading to confusion everywhere and accidental copies and bugs where people pass by value accidentally because its extremely easy to.
4. Channels aren't really that useful beyond small programs (IMHO, maybe I'm wrong), and by making them synchronous any non-trivial go concurrent program has to reason very carefully to avoid deadlocks.
There are countless similar things. People will put up with these idiosyncracies for a while but move on in the end.