Setting up a Go Development Environment 24 Mar 2013
I quite like Go, but some things about its standard practices are downright weird if you are coming from a more standard, project-centric approach to hackery. I don’t always (okay, usually) follow these standard practices personally, but anyone coming to Go should probably understand them and work with them, so that things in the wider community make sense. Everything I say here is my understanding of practices, and is probably wrong, so correct me if I am, for the sake of anyone else finding this article!
The first thing to grok is the idea of workspaces. I don’t know if this is any kind of commonly accepted term, but I have seen it used in #go-nuts and elsewhere, so I use it as well. A workspace is a space which holds projects, yours and anything you depend on (and usually a spattering of random things you experimented with and forgot about). You want to check out your project into your workspace, at the correct path.
We’ll make our hypothetical workspace at
$ mkdir -p ~/src/gospace $ export GOPATH=~/src/gospace $ export PATH=~/src/gospace/bin:$PATH $ cd ~/src/gospace
Within this workspace we have three root directories,
src which hold source code,
pkg which holds compiled bits, and
bin which holds executables.
We set the
GOPATH to point at your workspace, and add the
bin/ for the workspace to our
PATH. You can have multiple paths in your
GOPATH if you want to, and I know of folks who do, but I haven’t figured out how it makes life easier yet, so I don’t.
(update: Charles Hooper pointed out
bin/ subdirectories in the workspace will be created automatically when they are needed.)
Let’s say you want to work on a project called
variant, and you will host the source code on Github at github.com/brianm/variant. You will need to check this out to
~/src/gospace/src/github.com/brianm/variant. This is awkward, so we’ll just check it out via
go get and fix it up:
$ cd ~/src/gospace $ go get github.com/brianm/variant $ cd src/github.com/brianm/variant $ git checkout master
This works if your project already exists, if it doesn’t, you’ll need to go make the directories and set up the project basics, something like:
$ cd ~/src/gospace $ mkdir -p src/github.com/brianm/variant $ cd src/github.com/brianm/variant $ touch README.md $ git init $ git remote add origin https://github.com/brianm/variant.git $ git push -u origin master
Assuming the github repo is waiting for you. This isn’t a git/github tutorial though :-)
Your project’s place in the workspace is intimately tied to the source repo for it as Go’s dependency resolution mechanism relies on import paths matching up with source repos. It is kind of weird, and has some drawbacks, but is also really convenient (when you don’t hit those drawbacks).
Working on Your Project
For the package you are hacking on,
cd into the dir of the package, hack, run
go test or
go build or
go install as you want. Both default to the “current dir” which does a reasonable job of figuring things out (as long as you don’t have symlinks involved, Go hates symlinks for some reason).
If you want to fetch something else,
go get it. If you want to use the MyMySql driver/library you can
go get github.com/ziutek/mymysql and it will fetch and build it for you (and its dependencies). The source will be at
~/src/gospace/src/github.com/ziutek/mymysql, just like your project sources. It will be a git clone of repo. If you want a specific version (say the v1.4.5 tag),
cd over to it and
git checkout v1.4.5.
If you want to install a utility written in Go,
go get it as well. For example, to install dotCloud’s Docker you can
go get github.com/dotcloud/docker/docker. The target for the
go get is the package name (that would be imported) for the main package of what you want. It will fetch it, build it, and put the binary in
~/src/gospace/bin for you. (update: Jeff Hodges noted
go get will install things as happily as
install, so I simplified this and just used
go get instead of the earlier described
Working on stuff in Go like this is fairly painless while you are working in it but gets kind of painful when you want to do some things that are otherwise totally rational – like have repeatable builds (when you have dependencies) based on a tag in your project, or being able to just check out a project and build it without setting up a bunch of magical directories you just have to know about.
To be honest, these things, and a couple other odd caveats, deserve a post on their own, so with that, we’ll adjourn until then.
Please Correct Me!
If you have a better setup, or I thoroughly misunderstand something, please comment. I am still trying to figure out the best ways of doing things, and am very confident that I don’t have anything optimal yet.