In the following series of posts, I will outline the process of building a command-line tool. The easiest way to master a programming language is by building something tangible — something useful, or something one is passionate about! I have chosen to rewrite (most of) the awesome Engine Yard Ruby gem in Go. If all goes according to plan, the result will be a binary with zero runtime dependencies, easier installation, and hopefully faster deployments.

BY THE WAY… If you need badass dudes with true ops-chops to manage your infrastructure, I recommend trying Engine Yard!

Sign up for a free trial — 500 free hours on one or more instances!

Beginning a new project

$ ey NAME:

ey — The Engine Yard command line utility USAGE:

ey [global options] command [command options] [arguments…] VERSION:

0.1.0 ...

I am assuming you have a fully-functioning local Go environment. Let’s start out by creating a new project in our GOPATH: gitlab.com/voxxit/ey.

NOTE: It’s important to follow the workspace nomenclature, as this is how other Go projects may reference any library or public API you may provide.

Command-line tools usually consist at least one, but usually more than one command — forks of the main program which the user may request by name. It is important to quickly go over a typical Go-based command-line tool’s project structure:

$ tree

.

├── CHANGELOG.md

├── LICENSE

├── Makefile

├── README.md

├── command/

│ ├── deploy.go

│ ├── environments.go

│ ├── init.go

│ ├── login.go

│ ├── logs.go

│ ├── rebuild.go

│ ├── recipes.go

│ ├── rollback.go

│ ├── servers.go

│ ├── ssh.go

│ ├── status.go

│ └── web.go

└── main.go 1 directory, 18 files

main.go —

Executable commands in Go must always use package main. This file should be pretty simple: it should define the tool (name, usage, author, etc.) and then branch out tasks to the command package. This may seem familiar, as this is pretty much the way you’d start out a program in C, too!

command/NAME.go —

For each command, we will create a new file with the command name and the .go suffix. For instance, the command “ey deploy” code would live at command/deploy.go.

Makefile —

After typing “go build” a few hundred times, or once you need to support more than one platform, you’ll probably want a Makefile for your Go command-line utility will be a necessity. There are lots of examples for you to get inspiration from. For our tool, though, we’ll keep it simple: it will build our tool for the Mac, Windows & Linux platforms, and run our tests for us.

Laying out the project

I cannot name a single Go programmer in the know who would deny this: Jeremy Saenz is truly a “code gangsta!” Soon after I wrote my first CLI tool from scratch using only the flag package (part of the Go standard library) I discovered his awesome cli project on GitHub.

By importing this project into our project, much of the necessary framework we’ll need to get going with our CLI tool is already done.

Use “go get” to fetch this package so we can use it:

$ go get github.com/codegangsta/cli

Now, we can start writing the main.go file:

Seem a bit too simple? I’ll explain it step-by-step:

package main

As I mentioned before, all command line executables in Go must start from the main package. The presence of the main package will tell the Go compiler that it should compile an executable program instead of a shared library.

import (

“os” “github.com/codegangsta/cli”

)

import instructs the compiler to pull a package from your workspace into your program. In this case, I’ve imported the github.com/codegangsta/cli library, as well as the os package from the standard library — used to grab the command-line arguments.

var app *cli.App

By using var outside of the main function, we can create a placeholder for our app variable. This instructs the compiler to allocate enough storage for the variable when it compiles the program.

func main() {

// Create a new app instance

app = cli.NewApp() // Define the app we’re building

app.Name = “ey”

app.Usage = “The Engine Yard command line utility”

app.Version = “0.1.0” // Run the app, with the given arguments

app.Run(os.Args)

}

The main function is the starting point of all Go programs. It is the first function which is executed. In our main function, we initialize a new cli.App instance (using our app variable from before) and define a few of the values of the app. Finally, we call our app instance’s public Run method.

Voilà! You should now be able to run “go build”, then run the freshly-compiled binary to see the following: