Back to the Lab (again)

Go+

A simple proof-of-concept script for doing go dependency management.

Compared to other languages go has some strange behavior regarding its project root settings. If you import a library called `somelib`, go will look for a `src/somelib` folder in all of the folders in the `$GOPATH` environment variable. This works nicely for globally installed packages, but it makes encapsulating a project with a specific version, or modified version, rather tedious. Whenever you go to work on this project you'll have to add its path to your `$GOPATH`, or add the path permanently, which could break other projects which may use a different version of `somelib`.

My solution is in the form of a simple script I'm calling go+. go+ will search in currrent directory and all of its parents for a file called `GOPROJROOT`. If it finds that file in a directory, it prepends that directory's absolute path to your `$GOPATH` and stops the search. Regardless of whether or not `GOPROJROOT` was found go+ will passthrough all arguments to the actual go call. The modification to `$GOPATH` will only last the duration of the call.

As an example, consider the following:

/tmp
    /hello
        GOPROJROOT
        /src
            /somelib/somelib.go
            /hello.go

If `hello.go` depends on `somelib`, as long as you run go+ from `/tmp/hello` or one of its children your project will still compile

Here is the source code for go+:

#!/bin/sh

SEARCHING_FOR=GOPROJROOT
ORIG_DIR=$(pwd)

STOPSEARCH=0
SEARCH_DIR=$ORIG_DIR
while [ $STOPSEARCH = 0 ]; do

    RES=$( find $SEARCH_DIR -maxdepth 1 -type f -name $SEARCHING_FOR | \
           grep -P "$SEARCHING_FOR$" | \
           head -n1 )

    if [ "$RES" = "" ]; then
        if [ "$SEARCH_DIR" = "/" ]; then
            STOPSEARCH=1
        fi
        cd ..
        SEARCH_DIR=$(pwd)
    else
        export GOPATH=$SEARCH_DIR:$GOPATH
        STOPSEARCH=1
    fi
done

cd "$ORIG_DIR"
exec go $@

UPDATE: Goat

I'm leaving this post for posterity, but go+ has some serious flaws in it. For one, it doesn't allow for specifying the version of a dependency you want to use. To this end, I wrote goat which does all the things go+ does, plus real dependency management, PLUS it is built in a way that if you've been following go's best-practices for code organization you shouldn't have to change any of your existing code AT ALL. It's cool, check it out.

goat

-----

Published 2013-07-11


This site is a mirror of my gemini capsule. The equivalent gemini page can be found here, and you can learn more about gemini at my 🚀 What is Gemini? page.


Hi! I'm available for remote contract work. You can learn more about me and my skillset by browsing around this site, head over to my resume to find my actual work history, and shoot me an email when you're ready to get in touch.