Last year I've been considering and experimenting with learning another compiled programming language, which would supplement Python which I normally use for, well... almost everything nowadays. There's really only one objective reason for this: performance. With Python, it simply never gets better, and Python 3 is a mess, with basically non-existent PyPy support. Sure, I could write performance-sensitive parts in C (or C++) and use them from Python, but... no, just no. The things I do benefit from Python's rapid development mindset, and switching a web app to a C module would mean writing almost all of it (at least all of the web stack and libraries) in C.
Some numbers which support the performance problem conclusion:
- The Benchmarks Game (note that Go, surprisingly, has a much slower regex library than Python, I've seen this reported by multiple sources).
- Node vs Python vs Go vs Java vs Ruby.
- Some benchmarks of different languages.
Prediction: If Python 4 doesn't get rid of the GIL and introduce a high-quality (at least PyPy-grade) JIT at the same time, the language will die by 2020 (by which I mean its popularity will drop below Perl's).
I considered Rust, Nim, Go and D as possible candidates and decided to learn Go. The reasons, here, are mostly subjective and educated guesses, and may not apply to everyone. I consider Rust's syntax unreasonably weird and too verbose. While I like Nim's syntax (I like the "flow" of languages like Python and Pascal, even SQL), some of the decisions they made about the language are again "strange for the sake of strangeness", like "demoting" unsigned integers, and refusing to add Unicode-aware toUpper/toLower functions. I think D is good, only too similar to C++, which also means I wouldn't use it where I wouldn't use C++. So, Go it is.
If course, Go's not without its flaws, some of which bite me often.
Choosing frameworks and libraries
The first things I did was search around for frameworks and libraries which have semantics already familiar to me. Go's standard library has a reasonably good HTTP server / web app support, which is apparently a bit limited and used only in short or demo apps. So, here's what I've ended up with:
- Goji as the framework / URL router
- Gorilla Sessions for client-side and server-side sessions (since session support is not implemented by default in neither the Go library nor in Goji)
- Pongo2 Templates for Django-compatible HTML templates
So far, an example web app (a trivial CMS) running on a Raspberry Py 2, using SQLite as a database, responds with around 300 pages per second per CPU core, a performance which can only be dreamed about with Python. The price is, at a guess, about two times the amount of code than would have been needed with Python + Flask or more with Python + Django. Of course, there is (yet) no Django-like "admin" functionality nor automatic ORM operations. In the future, I might try using GORM.
Deploying Go web apps
To run my web app on Ubuntu, I've simply written an Ubuntu Upstart configuration file, which means all logging and restart-on-crashes is handled by Upstart automagically. I've put Nginx in front of the web app to handle static files, which could in a larger application also work as a load-balancer.
It's possible there are more idiomatic deployment options. I think this one is fairly efficient and performant.