2013-10-17 00:29:35 +00:00
|
|
|
---
|
|
|
|
layout: post
|
|
|
|
title: Go+
|
|
|
|
---
|
2013-07-12 01:27:58 +00:00
|
|
|
|
2013-10-09 02:26:08 +00:00
|
|
|
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
|
2013-07-12 01:27:58 +00:00
|
|
|
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
|
|
|
|
```
|
|
|
|
|
2013-10-09 02:26:08 +00:00
|
|
|
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
|
2013-07-12 01:27:58 +00:00
|
|
|
|
|
|
|
Here is the source code for go+:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
#!/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 $@
|
|
|
|
```
|
2013-10-09 02:19:12 +00:00
|
|
|
|
|
|
|
# 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][0] 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.
|
|
|
|
|
|
|
|
[0]: http://github.com/mediocregopher/goat
|