Welcome
There has been a lot of buzz around Go (golang) lately. I don't tend to be an earlier adopter for new languages since a strong community and proven platform are critical when building software intended for production enviroments.
Go has matured quite a bit since it was introduced in 2007, so I decided to take a deeper look this week. My research concluded that it makes a good fit for scalabale (enterprise level) web apps, and API's in specific.
Go supports concurrency and multi-threading on the language level, right out of the box. It also enforces strict syntax and formatting rules - making your code more standardized and less error prone. There are other advantages like built in testing tools and fast compiling speed, but I won't harp on those too much. I don't consider either of those a differentiating factor.
I wanted to give Go a try and build a practical application that we would normally develop here at Kettle. A simple API, hooked up to MySQL seemed like the perfect concept.
Lets do this!
Prerequisites
Since I wanted to test the full life cycle of a Go application I needed to setup a remote enviroment on Heroku. I won't go into too much detail on how to set these up, but below are some resources that I found extremely helpful:
- Setting up Go locally on a Mac isn't very straight forward. You can use Homebrew here, but I'd suggest referencing the Offical Site & Ryan Day's Guide
- Setting up Go with Heroku was pretty straight forward using Mark McGranaghan's guide
The Code
I found a nifty framework called Martini that was designed to make the code more modular and quicker to write. I came up with the following code for my super simple sudo-API:
package main
import (
"github.com/go-martini/martini"
_ "github.com/go-sql-driver/mysql"
"database/sql"
"fmt"
)
func main() {
// Connect to database
db, err := sql.Open("mysql",
"user:pass@tcp(localhost:3306)/tableName")
// Fire up martini & define route
m := martini.Classic()
m.Get("/api/:id", func(params martini.Params) string {
// Define variables
var str string
var userId = params["id"]
// Run MySQL query against param
err = db.QueryRow(
"select name from users where id = ?", userId).Scan(&str)
// Check for errors and log if they exist
if err != nil && err != sql.ErrNoRows {
fmt.Println(err)
}
return str
})
m.Run()
defer db.Close()
}
Just How Fast Is It?
Now that I had a functioning piece of Go code I wanted to see just how fast the language was. After hearing all the praises of the language I needed to see first hand how good/bad it was.
To test the app I used a service called Loader.io (awesome tool by the way). I had Loader query the service with 4,000 clients (making 2 requests each) over the course of 60 seconds and these are the results I saw:
The results are astounding. I was running a free Heroku instance and free database from ClearDB. Regardless of those limitations, the app managed an average response of 35ms with zero errors. I found this impressive for three reasons:
- The response times were quick and consistent
- The error rate was zero which is important
- The app handled many requests per second on limited server resources without issue (think: cheap infastructure costs at scale)
Compared to Laravel 5
My intention here was to learn Go and see if it was really as good as people said. After seeing the results, I'm pretty convinced it is good. However, I was curious to see how it would stack up against Laravel 5, an awesome PHP framework we use quite often here at Kettle. I knew this wasn't a fair comparision, but I did it anyway. Here is the code we used in Laravel:
routes.php
<?php
Route::get('/', 'WelcomeController@index');
Route::get('/api/{user}', 'ApiController@user');
ApiController.php
<?php
namespace App\Http\Controllers;
use DB;
class ApiController extends Controller {
public function user($user) {
$response = DB::table('users')->where('id', $user)->first();
return $response->name;
}
}
I ran the same test again - 4,000 clients over the course of 60 seconds, each making 2 requests. These are the results observed:
Conclusion
As expected, Laravel performed much slower than Go. I believe Go is a great choice for something like an enterprise API. It's quick and predicable. This makes it easy to scale.
Laravel has it's place too - it allows us to build robust web apps, quickly. That makes it a great fit for projects that require quick turn around and agile development.
We hope you enjoyed this article. Please feel free to leave comments below.