Go is great, but I just had to do something about its borderline insane dependency management.
Being able to do import github.com/foo/bar
is cute, but there’s very little guarantee that dependencies won’t change overnight, and no practical way of pinning stuff to a specific version/revision. Having a strong desire to avoid a repeat of my early experiences with NodeJS, where stuff like express
broke all of my code a few weeks down the road, I started looking for solutions early on.
But all the approaches I came across required third-party tools that are entirely too much hassle to set up and use reproducibly, so after a little experimentation, I converged on a rather lazy approach that mimics my usual Python pattern:
I set GOPATH
to a vendor
directory inside each project repository, go dep
into that and clean out the .git
/.hg
folders in order to commit all the dependencies together with the project.
It’s a little wasteful in terms of storage, but perfectly doable for my ongoing projects and ensures that I’ll be able to rebuild things six months down the line. Plus it’s trivial to automate with a Makefile
like so (which also makes it easy for me to do cross-compiles):
export GOPATH:=$(shell pwd)/vendor
export PATH:=$(PATH):$(GOPATH)/bin
BINARY=foobar
$(BINARY): *.go
go build -o $(BINARY)
deps:
mkdir -p vendor
go get github.com/rakyll/globalconf
go get github.com/efarrer/iothrottler
find vendor -name .git | xargs rm -rf
find vendor -name .hg | xargs rm -rf
git add vendor/src
clean:
rm -f $(BINARY)
go fmt *.go
pi:
GOARCH=arm GOARM=6 go build -o $(BINARY)-rpi
synology:
GOARCH=arm GOARM=5 go build -o $(BINARY)-syno
So to add a dependency I just add another go get
line, do a make deps
and all the required code is added to the project. To update a dependency, I just remove its files and do it again. A trifle unsubtle, for sure, but it works, and has the additional side benefit of my being able to organize my projects anywhere on the filesystem without having to submit to Go’s “there can be only one way to organize your code” silliness.
Since make
is available pretty much everywhere and not something that is likely to go out of fashion (outside the NodeJS world, that is, where they keep reinventing it), I think this solves my problems for the foreseeable future – or until Go standardizes on something at least as simple to use and maintain.