Like every week there were the usual announcements of new stuff from Google this week. Highlight this week must be the experimental language Go. My initial response, not hindered by any knowledge about what Go is about, was: yet another language, why bother? I watched the rather interesting techtalk about this new language and I have a bit more insight now. My initial response is still prevailing, but I can see how Go could influence things in the right direction since it does do a few cool things.
Things I like about Go:
- Channels and “go routines” aka. jobs or threads if you insist (not necessarily the OS supported ones) supported in the language, this is the essential superglue needed for parallel computing. The only mainstream language that comes close so far here is erlang, which is not exactly very popular but is being applied successfully for e.g. xmpp implementations. Anybody who has ever done any programming involving threads should be able to see the benefit of these features. I need this, yesterday.
- Interfaces and typing. Any interface declared is automatically a type of anything that implements its contents. This is a useful formalization of duck typing (if it walks & talks like a duck, it must be a duck) that I haven’t really seen elsewhere other than scripting languages. It’s a bit of a philosophical thing. Should objects describe themselves, or or should an outsider be able to classify the world? Go takes the outsider point of view and basically allows programmers to treat objects as a Duck if they implement a quack() method. Like it or not, concepts like casting, the friendly keyword in C and untyped languages exist because of this. Go doesn’t need those.
- Orthogonal & KISS design of the language where things can be combined freely. Some pretty cool stuff was demoed with channels, consts and other language features being combined to do pretty complicated stuff in the above linked techtalk. Separation of concern is highly useful, as any good software designer knows, and the right thing to have at the language level.
- Implicit typing of arbitrary precision numbers, floats, etc. This is a brilliant idea. Prematurely narrowing down the precision of your floats, ints, and what not is a source of bugs. Leave it up to the compiler to figure out the right precision and leave it to static code analysis tools to identify potential performance bottlenecks that might result from this.
What I don’t like:
- C-like syntax & weird syntax for types. C syntax was never that great (without macros, C would be unusable) and essentially most of the details were bolted on over time. Preserving the error prone & and * notations is in my view a big mistake, as are several other C constructs. They are an open invitation for programmers to make extremely hard to find mistakes.
- Lack of generics, although they are working on a solution here apparently. Like it or not, meta programming and related subjects are enabled by this key feature. Too important to omit nowadays.
- Yet another vm/runtime and no support for JVM, .Net, llvm, or similar run-times. In my view native is overrated (relative to dynamic compilation) and I don’t buy the “runs within 10-20% of native C code” claim (what about optimizations & 40 years of compiler tweaking?). But I’m sure that is true for the trivial code that has so far been written in Go. As is the case for trivial Java code, which under controlled circumstances kicks some ass relative to any statically compiled language BTW. But show me some real software doing real stuff.
- Burn everything and start from scratch approach to libraries. Is that really necessary? Seriously, I spent the past few days sorting out the dependencies to external libraries I have in a ‘simple’ java project (i.e. updating to more recent versions, pruning unused stuff). Contrary to the popular belief, some of those ~50 direct and transitive dependencies do some really useful things and are not just bloat. 5000 lines of Java + a few hundred thousand LOC in dependencies is hard to beat with a new language plus ~100KLOC worth of libraries. Any productivity gains would be wiped out by having to reinvent a lot of wheels. Not necessary in my view.
- The nineteen seventies architecture for compiler and run-time. As I outlined in my last post, I believe compilation is fundamentally a run-time optimization these days. With Go, the compilation work is allegedly light to begin with due to the wise decision to keep the language simple. So why bother at all with compiling and why not just leave things to the run-time to figure out when you actually run the code? Integrate the compiler into the run-time and remove compilation as a concern for developers.
In short, nice concepts but I don’t see the need for tearing down everything we have and starting from scratch. Basically this language is scala + a couple of tweaks and minus all of the integration work and maturity. There are lots of contenders in this space and Go is just yet another one. They probably should have called it E since it is just repeating the mistakes of C, C++, and D but is not quite the same as F#.