By polite I mean not interfering in any other projects (even Golang ones), not polluting or forcing your global workspace (no matter how it is organized), and being reproducible on any other machine. For reasons out of the scope of this document, that's not an easy task to accomplish when working with Golang.
These are my notes, not a generic solution. They are not meant to work anywhere outside my machines.
asdf
lives in https://github.com/asdf-vm/asdf
Follow its installation instructions, which at the moment of writing were:
cd
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.4.3
# For Ubuntu or other linux distros
echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
On a new terminal, install Golang plugin:
asdf plugin-add golang https://github.com/kennyp/asdf-golang
Then install Golang:
asdf install golang 1.10.1
Set some Golang verion as global. You will need it to setup your environment afterwards:
asdf global golang 1.10.1
These are a couple of functions that are handy to manage golang workspace. Add them to your .bashrc
, then put the ingopath
call in the prompt as well:
######## golang stuff
# This goes up from current folder looking for a folder
# that looks like a golang workspace root (has a 'src' subfolder, by now).
# Then echoes its path and returns 0.
# Returns -1 if does not find such a folder.
function detect_go_workspace_root {
path="$PWD"
while [[ $path != / ]];
do
src="$path/src"
if [ -d "$src" ]; then
echo "$path" && return 0
fi
path="$(realpath -s "$path"/..)" # ignoring symlinks
done
return -1
}
# This will setup the Go workspace to the detected root path.
# It will complain if not detected.
# Then it will cd into folder pointed by $GOPATH/.letsgo_srcpath
function letsgo {
root=$(detect_go_workspace_root)
if [ $? -ne 0 ]; then
echo "Could not find Go Workspace Root for $PWD" && return -1
fi
export GOPATH=$root
export GOBIN=$root/bin
export PATH=$GOBIN:$PATH
export GOROOT=$(go env GOROOT)
srcpath="$root/.letsgo_srcpath"
[ -L "$srcpath" ] && cd "$(readlink $srcpath)"
}
# This will echo some funny symbol if we are inside current GOPATH.
function ingopath {
[[ $PWD == "$(go env GOPATH)"* ]] && echo "(👀)"
}
## then in the prompt
export PS1='bla bla \[\033[00;36m\]$(ingopath)\[\033[00m\] bla bla $ '
Create a folder for your workspace, then put a src
folder inside it, and cd
into it. Then run letsgo
.
~ $ mkdir -p my_project/src
~ $ cd my_project/
~/my_project $ letsgo
~/my_project(👀) $ # <------ see the eyes, we're inside the GOPATH
At this point you have a pristine golang workspace to follow mainstream conventions (See https://golang.org/doc/code.html).
-
Not existing repo
If this is a new project you should create a folder for your source code, creating folders after your repo's URL path:
mkdir -p src/github.com/rubencaro/my_project cd src/github.com/rubencaro/my_project
That's the folder that gets into version control. You should setup
git
now. From inside that folder, something like:git init
echo "# My Project" > README.md
git add .
git commit -m'First commit'
git remote add <blabblablab>
git push -u origin master
-
Already existing repo
If your project already exists on some repo, you can do:
go get -d github.com/rubencaro/my_project cd src/github.com/rubencaro/my_project
That will create the folders for you.
If you happen to be using SSH to authenticate with github (I recommend that), then you may want to add this to your .gitconfig
:
[url "[email protected]:"]
insteadOf = https://github.com/
This will prevent go get
from using https login when accessing github.
Fix your golang version running asdf local golang 1.8.3
on your source code folder. That will create a .tool-versions
file that should be included into version control. That file sets the golang (among others) version to be run when inside this folder.
Then you link that file to the root of your workspace, so everyone in the workspace uses the same golang version you configure on your repo:
ln -s $PWD/.tool-versions $GOPATH/
If the version you just fixed was different from the current one (see go version
), then you should continue from a new terminal and run letsgo
again to ensure your go version is the one you chose. You can run go env
if you are in doubt of anything misconfigured.
cd
into your source code folder and run this:
ln -s "$PWD" "$GOPATH/.letsgo_srcpath"
This makes a link in your $GOPATH
that will make letsgo
get you into this folder after setting all Go environment. This is useful to avoid repeated cd src/github.com/blahblah/blahblah
every time.
From your source code folder run:
go get -u github.com/golang/dep/cmd/dep
Remember this installs dep
only on this workspace. Not on global.
-
A new project, first
dep
run:- You should run
dep init
to create theGopkg.toml
andGopkg.lock
files. See https://github.com/golang/dep for further info. - Ignore the
vendor
folder from your version controlecho "vendor" >> .gitignore
. You only need to keep track of both theGopkg.*
files. - Now you can commit your changes to
.gitignore
,Gopkg.toml
andGopkg.lock
files.
- You should run
-
An existing project: Simply run
dep ensure
to install on the workspace everything specified in theGopkg.lock
file. There should be no change on yourgit status
.
The first thing to do is always to run letsgo
from anywhere inside your workspace folder. That will point your GOPATH
to the detected workspace root path, and add $GOPATH/bin
to the PATH
. Then you can open your favourite editor and compile, do your thing. Everything done from there will work with the project dependencies, golang version, etc. You can see the little eyes (or whatever funny symbol you return from the ingopath
function) indicating you are somewhere inside your GOPATH
.
If you fail to do that, just forgetting, or opening a new terminal and not running letsgo
, then you will be working with the global GOPATH
, meaning that you will Go to Hell (pun intended). You will mix up everything from your different golang projects. You may be mixing binaries compiled from different golang versions, or mixing different versions of the same libraries, and so on.
Remember to always run letsgo
before start working on your project.
Any new version of golang may come out, you simply install it using asdf install golang <newversion>
. Then to try it on your project, go to the source folder and run asdf local golang <newversion>
. That will change your .tool-versions
file, and thus change the golang version used everywhere inside your workspace. Remember to recompile everything using the new golang to see if it all checks out.
See https://github.com/golang/dep for details. Taken from there:
import
the package in your*.go
source code file(s).- Run the following command to update your
Gopkg.lock
and populatevendor/
with the new dependency.
dep ensure
How can I upgrade golang version in asdf?