So, how do I feel about Go, now that I know it better?
On the whole, I like it. Some high points:
It’s reasonably terse, and there’s not much syntax to remember. Like Ruby, you can do a lot in not much code, and unlike (say) Java there isn’t really a big need for an IDE.
It inherits from Modula-2 a focus on compile-time efficiency. No header files, a compact grammar, and rigid dependency declaration make for rapid compilation times.
Performance is good, often comparable to C++.
Cross-compilation is easy. On my Mac I can
GOOS=linux GOARCH=386 go build hello.goand get a binary that I can just rsync to my Linux box and run there. And…
Deployment is easy: The compiler spits out a single binary, and that’s all you need. You don’t need any sort of Go runtime installed on the destination system.
Like Ruby, you don’t have to rigidly specify what interfaces your objects support; it’s all duck typed.
The speed of the tools and ease of deployment make programming in Go a curiously retro experience. It feels a bit like I’m back sitting in front of a copy of Turbo Pascal.
What don’t I like? Oh, a few things:
There are two different syntaxes for variable declaration, and you have to know and use both of them. (Well, it might be possible to do without
:=, but not without painful workarounds making the code ugly.)
No tail-call elimination (yet). Sometimes recursion is the best way to do something.
The standard logging library is poor. No levels, no level guards, and a gratuitously non-standard date/time format.
Variables aren’t immutable by default.
Pointers are visible.
I don’t view any of these as deal-killers, though. In fact, I’d like to go through a few things other people often cite as criticisms of Go, which I think are features rather than bugs…
Speaking as someone who writes Java for a living most weeks, I view Java’s approach to error-handling to be a well-intentioned experiment that has failed. Forcing bad programmers to pay attention to exceptions doesn’t work. In practice, they write code which catches and eats them, or fails to process them properly. (Try finding a single correct piece of example code to perform a JDBC query, dealing cleanly with all possible exceptions.)
Young programmers think they can handle memory manually, and do it right. About 40 years of industry security incidents suggests otherwise. A modern memory manager is almost as fast as well-written hand-optimized code. For almost all of the programmers almost all of the time, doing memory management manually makes as much sense as writing in assembler.
No generics yet
Sure, generics are useful in Java. They are also a major pain in Java. I’d rather wait and have them done properly in Go, than have a hurried ugly solution.
As long as you’re not a language snob, I recommend taking a look at Go. It doesn’t do everything right, but it does a lot of things right.
There’s a video of a talk by Rob Pike where he talks about Go’s focus on simplicity above almost everything else.
I like simple languages, and I think that’s why Go appeals to me. I like Scheme, and I like Ruby. (Ruby’s grammar is complicated, but to the human it’s very simple and consistent.) The simplicity is why I ditched Perl for Ruby. It’s why I prefer Objective-C to C++.
Overall, I think Go is one of the best new languages. The only other ones that interest me right now are Rust and Swift. As far as Rust goes, I’m not completely convinced that squeezing that last bit of performance out of the system is worth the hassle of manual memory management. With regard to Swift, it seems similar in many ways to Go, but with the benefit of excellent Mac OS X support.