Stacks on Stacks

Learning Go: Porting an Application

I recently started learning the Go programming language as it is widely used at my new workplace. When I start learning a new language, I usually like to start by doing the obligatory “Hello World” program, then reading up on the languages internals, and finally, I like to actually apply all those concepts to an actual project. While learning Go, I realized exactly what project I wanted to apply it to.

I had previously written a utility in python, ilo-utils, which searches a subnet for all iLO devices and prints a summary of them with some basic information. The output looks something like this:

ilo-utils screenshot

My goal was to try to recreate this functionality using Go, since go has some really nice concurrency concepts built in. From what I have read, if you make use of these concepts, then your program can use all operating system resources available to it, achieving parallelism when able. I watched a great video on a talk given by Rob Pike called Concurrency Is Not Parallelism. It was definitely a great talk and as a go newbie, it really helped me.

Porting to Go

The first challenge that awaited me after deciding to port my program, was that I had no way of testing it. I didn’t have access to any iLO servers anymore. So my first priority was to create a simple server in Go that mimicked the behavior of an iLO server.

Go makes it really easy to write code that can be distributed as a package for use in other programs while also being able to consume it if you wish to distribute your binaries. The convention that I followed after looking at a lot of go repos is that you create a cmd directory in your package root and then make a folder with the name of each binary you wish to distribute. In my case, my repo structure had the following directories: cmd/ilo-sweep and cmd/ilo-server.

Porting all of the code over to Go was pretty straightforward. Having worked mainly in Python and Ruby for the past few years, it was definitely a little different and took me longer to write code as I had to learn the Go way of doing things, but overall, not too bad.

Testing

Testing was the next hard part. I needed a way to stand up a bunch of different servers on different network interfaces. Now, I could have used a bunch of VMs to run the ilo-server code but that seemed like a lot of overkill. Besides, I have been working with Docker for the last few years and with some of the new networking features, I figured that might work for me. I wasn’t disappointed.

I was easily able to use docker-compose to set up a bridged network, scale up a number of iLO servers, and then test out both my go code and my python code pretty easily to ensure I was building the same thing.

Results

Overall, my results were pretty great. I was able to port over most of the functionality, while learning go at the same time. Here is a screenshot of both the python program output and the go output:

ilo-sweep comparision

Conclusions

Go makes it fairly easy to write concurrent programs as it has great primitives like goroutines and channels built into the language. It is also very fast to both compile and to run. I can easily see this being my first choice going forward when working on a new project. One thing I especially like is that you can compile it ahead of time for different architectures and then you only have to distribute a binary. This is appealing as it lowers the barrier for others to consume your program since they don’t have to ensure they have the correct version of Ruby or Python, etc.

If you want to see what I ended up with, check out the code on GitHub here