November 19, 2014
What we're up to
At Shipwire, we’ve started to fold Go into our technology stack. In this post, I’d like to explain why, and in doing so, address some recent concerns about the language.
Shipwire and I have a shared history of PHP. (We know, we’re working on it.) When we did our early development in 2007 and before, it was ubiquitous. Alternatives at the time were either ill-fit for web applications or required more than affordable commodity hardware—neither great choices for early-stage startups or young students trying to learn the Internet.
All languages have trade-offs and find a balance between expressiveness, complexity, speed, and safety. Java, for instance, is fairly safe and fast (when done well), but can be verbose, growing into difficult-to-tame beasts. PHP, on the other hand, is relatively slow in pure computational tasks but lets you choose between expressiveness and safety. Sometimes there are other variables in play. Haskell, for instance, gives you great expressiveness, speed, and renowned safety, but it is complex when it comes to programmer introduction. Haskell is a great language, it just requires a big investment unless you’re already interested in functional programming. The conclusion I’ve made is that Go makes the right set of trade-offs for most of our projects.
When reasoning about feature inclusion, Go generally makes one of three choices:
- Add a relatively simple implementation into the language
- Accomplish something through tooling (or runtime)
- Leave out a feature
What this means
This means that all Go language features are either relatively simple, totally transparent, or decidedly absent, and in no case did the Go team choose an existing model when it could be made easier to read or understand. All of the often remarked strengths and flaws in Go could be attributed to one of these points.
All of these give the language great power and efficiency without adding significant complexity and have been written about at length.
These “flaws” are all works in progress. The Go team has been vocal about their goals for garbage collection, bringing it to a point where it has no impact for most use cases (at least that we have). The type system is not perfect: there’s nil, no algebraic data types, no monadic data types, there’s the empty interface and the unsafe package, and then there’s the lack of Generics. I'd like to do that topic justice in a later post, but roughly: I find that my code ends up simpler without them. As for dependency management, the community has developed several ways to manage that. Different solutions work better in various cases, so it seems right the language hasn't adopted one.
Only the beginning
Go isn’t meant to be an end-all-be-all solution to every problem. It’s meant to be a great tool where these trade-offs happen to work well. Having spent close to a thousand hours writing Go, I still find myself pleasantly surprised by the language and by the quality of the code I can easily produce in it.
The caveat to this, is that it’s still possible to write bad Go. It’s been done before (including by me), and I’ve written about it. That said, the community around the language has stepped up to strive toward idioms that complement the language and we’ve become better programmers for it (more on this in a later post). We’ve a high bar for ourselves, but the work that’s going on is surpassing it at nearly every turn. This is becoming one of the best parts of the language. It feels like a fresh start where we can hold ourselves accountable where we might otherwise introduce complexity. We can see the results of this too: the ecosystem is thriving with great projects.
Myself, personally, and we at Shipwire, are excited to continue this growth. In the coming months, we’ll be announcing a few open source projects and a few more blog posts that we think will bring us a few steps further. Happy coding!