Oh dear… I’ve just fallen very, very, hard for a brand new software development language. Don’t tell Perl, C, Java or VB.NET. If they knew how my heart is singing on this new one, they’d be devastated.
It’s called Go[lang], and now I’ve had a week with it, I can’t help think thinking that this little number from Garbage should be the theme tune:
It’s breaking hearts, and leaving competitors at the stable gates. It’s dangerously oblivious to its own stunning beauty and sleek aerodynamic curves. It has me all “Danny Zuko” messed-up with its “Sandy Olsson” mix of wholesome static-typing mixed in with a bunch of wicked get-outa-the-road-code-coming-through leathers!
I’ve had a little time to experiment for myself this week, and I took the opportunity to revisit a utility I built in Perl back in the day that I wasn’t terribly fond of. All I knew for sure at the start of the week is that a) it had language primitives for Hoare’s Communicating Sequential Processes (even to this day, I remember loving what that University subject did to my head-space), and b) Google invented it to deal with back-end server coding which means that it was probably designed for speed, even without concurrency.
Wikipedia’s discussion and the interactive online tutorial convinced me there was something to the language worth investigating. An (admittedly uncooked) Eclipse plugin, and a freeware DBF library got me across the wire with respect to the bare-minimum I’d consider as also needing for the experiment. If anybody is in contact with the DBF library maintainer, tell him to check his G+ messages. I have bug fixes for him.
Lots to cover here, but I’m in love, so I don’t mind singing the praises!
It’s DRY, and FAST to code with
Go[lang] is almost a hydrophobe in terms of it’s language features that just get the hell out of the way and let the programmer get down to it (like oh… Perl?). It compiles down to native executable code on it’s target platform, without the need of make files, header files, and even variable declarations that derive their type off the data they’re being initialised with.
I hadn’t realised it, but all that extra noise in C and C++ actively acts to calcify the code-base. If I change my mind on which functions live in which object files, I no longer have a painful dance with Make and re-aligning .h and .c files. Let me say that again. Go handles complete compile through to executable all by itself with nothing else to go on but source code. No more make file nightmares!
It means I’m far happier to completely re-jig design-level decisions on the fly.
Thanks to this little jaunt, it struck me that C and C++ both carry language features that are themselves, DRY violations. However, for peeps with a C or Java background, Go[lang] has such a strong C flavour to it, we’re into very familiar territory right off the bat:
Go development in Eclipse
And on coding with variables, I get the compiler still being absolutely rigid about matching types , but by not having to spell it all out myself, I’m thrilling to some of the benefits seen in interpreted languages where I can keep up the pace by not being forced to syntactically dot all my i’s and cross all my t’s.
The language allows multiple assignments at once. That means there’s no need for me to explicitly spell out needing a temporary variable to hold data over a swap operation. Coupled with functions now being allowed to return a tuple of values, and Go[lang] has a very natural feeling mechanism built into the language for propagating errors up the stack until the higher levels can make appropriate decisions on whether the errors are game-stoppers or not.
Here’s a screenie of cascading errors naturally through the stack:
Error Propagation in Go[lang]
There are also a number of language features that Go[lang] has adopted that I hold real fondness for:
- Garbage collection so I don’t have to constantly watch what I’ve done with every single byte of memory.
- No cancer of the semi-colon (and can we truly claim that it’s a C derivative if there’s no semi-colon per line?).
- It is object-oriented, with external visibility of attributes and methods derived off how you name the language construct.
- Removal of object inheritance, because let’s face it… I’m as dangerous with deeply nested inheritance as I am with being asked to manage memory allocation myself.
It’s Fast to Run Too
Did I say it runs fast? It runs fast. Not as fast as C, or C++, but apparently it trumps Java whilst also keeping garbage collection in the mix. My own desires here were far more modest. I wanted something fast to code in that would rid me of Perl’s lack-lustre run-time performance. And, I got my wish:
Perl (top) vs Go[lang] (bottom) Execution Speeds
Ten minutes in Perl down to just over ten seconds in Go[lang] for exactly the same algorithm. It’s also a lot kinder to run-time memory, requiring far, far less to pull the same trick off. That’ll do nicely thanks!
Let me also be clear here, I’ve made no use of the concurrency primitives that Go[lang] has to offer yet. It’s the same entirely sequential algorithm so far. I don’t expect such a huge gain when I start playing with concurrency, but I’m looking forward to trying out channels to allow the CPU(s) to keep busy when IO blocks.
Finally, the Go[lang] compiler acts as a daemon, running in the background. When it spots a source-file change, it recompiles so fast that in the time it takes me to ALT-TAB to a test console, the re-cooked executable is ready for me to run. Compressing that entire code-compile-run cycle down to code-run makes Go[lang] feel like it’s actually an interpreted language. I have no idea how well the compile scales for large builds, but for my modest test, it was pure pleasure.
Allow me a little sleight-of hand here to devote far less text to the Bad. It’s hoped that you’ll be not-so-subtly influenced to also dismiss the bad. Here’s a bunch of bullet-points spelling out the bad I’ve found to date:
- It’s got a young secondary (not Google) support market. You can tell by the lack of good examples available for typical code idioms in the language, and the under-cooked state of various support tools.
- The lack of semi-colons means occasional moments of fun for why source-code won’t compile. If for instance, you want to finish a command with a closing bracket on it’s own line, you’ll need something on the previous line to tell the compiler that the command isn’t finished yet.
- Being type-safe, it’s also occasionally painful to cast between compatible types. Given how much work’s been done to get out of the way in similar areas of the language, this seems a bit of a violation of the rule of least surprise.
- Once I realised I was dealing with native binaries compiled off a C-like language, I also expected it to perform closer to C++ than it does. No doubt, the compiler will produce more efficient binaries as time goes on.
- There’s no effort that I can see on GUI libraries (and why would there be?). Still, slap a good desktop GUI library on this puppy, and there may just be an exodus away from C++ by those who are tired of self-flagellation for the sake of speed.
- You’re dealing with pointers vs direct access to memory locations again. Reminiscent of C, but with more checks. We’re back to funky scenarios where we can pass pointers to function calls around just as easily as a constant. Thankfully, the compiler’s been mostly good to me on that score.
I’ve found Go[lang] only a tad slower to code in than Perl (which is a lot faster than Java, and honestly, pretty damn fast as languages go).
It’s blindingly fast to run compared to Perl, and looks like it gives Java a good run for its money as well.
Compile-times for my toy weren’t noticed by this slow meat brain, so it was also reminiscent to having an interpreted language on that score.
All in all, if I can find libraries for the bits I don’t want to code myself, I think I’ve found a new favourite “glue” language. Go Baby Go Go! 😉