← Home

Dividing a Go Project into Multiple Packages

I’ve recently become interested in the Go programming language, not because I’m attracted to its syntax or the goroutine/channel pattern for writing multithreaded code, but because I like the package management, build / testing tooling, static compilation and solid cross platform support (change the target and out pops a binary for that platform).

I’ve done done the online tutorials and read The Go Programming Language [0] cover-to-cover and started coding, but quite quickly I realised that I didn’t understand how I should lay out a larger project.

I read [1] which explains the layout of a project with a few packages in it, but it doesn’t go as far as to state how you’d compile all of the packages in a single step.

For once, it turned out to be easier than I expected.

If, like Dave Cheney’s blog post suggests, you have a directory for your project, e.g. a directory in your $GOPATH:

$GOPATH/src/github.com/[username]/[projectname]

And you create subdirectories for each library package that makes up your project (the convention is to use “main” for the entry point of executables).

$GOPATH/src/github.com/[username]/[projectname]/firstlibrary
$GOPATH/src/github.com/[username]/[projectname]/secondlibrary
$GOPATH/src/github.com/[username]/[projectname]/main

You can reference firstlibrary from main like this:

import (
    "fmt"

     "github.com/[username]/[projectname]/firstlibrary"
)

At this point, I thought I might that to push code to github.com, put together a bash script to build multiple projects in order etc., but fortunately the go command line tool is smart enough to work out dependencies, rebuild anything that’s changed locally and download source code from imported Packages.

So… to run or build the application, it’s as simple as cd $GOPATH/src/github.com/[username]/[projectname]/main and go run main.go or go build.

What a relief… so why did I think it was going to be more difficult than it was?

Coming from Python, I was thinking about setting up virtualenvs, switching between Python 2 and Python 3, using easy_install and pip to install packages, then finding that something is missing (gcc, some OS-specific set of packages). At first, I was also thinking about each Go Package being similar to a Module (where the file name determines its name) and trying to have more than one package in a directory (which isn’t allowed).

Coming from Java, I was thinking of each Go Package being similar to a Module in Maven, and having to define the dependencies at a top level somewhere, working out what Maven modules to use, looking up the XML syntax for the pom.xml file etc.

Coming from .Net, I was thinking about needing to create a Solution, setup relationships between Projects in the Solution and define external dependencies from Nuget repositories using the Package Manager Console. The new dotnet command line tools look a whole lot better, but from trying it out a few weeks ago, that toolset is far away from ready for production use.