Trying to understand GOPATH

191 views
Skip to first unread message

leon.j...@gmail.com

unread,
Sep 23, 2016, 12:13:30 AM9/23/16
to golang-nuts
I'm new to golang, and I'm trying to understand the role of GOPATH. The OS X package from https://golang.org/dl/ installs to `/usr/local/go/bin/go`. 

Do I have to manually symlink /usr/local/go/bin/go to my PATH because the GOPATH docs lead me to believe that GOPATH to need to be set to the 
directory where my go code is located. 

Example of my code directories:

git
├── bitbucket
│   └── demo1
├── github
│   ├── notes
│   ├── scripts
│   └── snippets
├── github-work
│   ├── ruby-app1
│   ├── ruby-app2
│   └── ruby-app3
└── gitlab
    ├── javascript-app1
    ├── python-app1
    └── (go-app1)

I'd like to be able to keep this structure the same, but I don't see how this is possible with GOPATH pointing to a single directory. 

What if I want to organize my code by version control location and not by language?

Volker Dobler

unread,
Sep 23, 2016, 2:00:00 AM9/23/16
to golang-nuts, leon.j...@gmail.com
There are two parts in your question:

Am Freitag, 23. September 2016 06:13:30 UTC+2 schrieb leon.j...@gmail.com:
[...]
Do I have to manually symlink /usr/local/go/bin/go to my PATH because the GOPATH docs lead me to believe that GOPATH to need to be set to the 
directory where my go code is located. 

1. Normally you append /usr/local/go/bin to your PATH variable so that you can
execute the go command by typing "go" in your terminal instead of having
to type "/usr/local/go/bin/go". This is for your convenience and completely 
unrelated to your Go source code. (Note that no symlinking is done anywhere
and this really not related to anything GOPATH is set to or not set to.)
  

2.

Example of my code directories:

git
├── bitbucket
│   └── demo1
├── github
│   ├── notes
│   ├── scripts
│   └── snippets
├── github-work
│   ├── ruby-app1
│   ├── ruby-app2
│   └── ruby-app3
└── gitlab
    ├── javascript-app1
    ├── python-app1
    └── (go-app1)

I'd like to be able to keep this structure the same, but I don't see how this is possible with GOPATH pointing to a single directory. 

What if I want to organize my code by version control location and not by language?

The documentation on GOPATH i pretty clear: You do not have any choices,
you must organise your code in one particular way.
GOPATH may point to several distinct directories (GOPATH is a list like PATH is),
but this still does not permit your desired code layout as each entry in GOPATH
must stick to the convention.

If you really want to keep this layout you can always use the Go compiler directly,
typically driven through a Makefile. As you are new to Go this will be a _major_
pain for you (it is a major pain for experienced Gophers), maybe even undoable.

There is no reason to not put you Go code in a GOPATH and go tool compatible
structure.

V.

leon.j...@gmail.com

unread,
Sep 23, 2016, 7:48:06 AM9/23/16
to golang-nuts, leon.j...@gmail.com
Thanks for the response, it makes sense now.

Diego Medina

unread,
Sep 23, 2016, 8:20:26 AM9/23/16
to golang-nuts, leon.j...@gmail.com
As you start working with Go, one other thing you may want to add to your ~/.bash_profile (on linux and mac, not sure about others) is




so let's say you have $GOPATH as 

/home/my-name/work/golang

and a project at $GOPATH/src/github.com/fmpwizard/my-project

without the CDPATH, you would have to do :

cd $GOPATH/src/github.com/fmpwizard/my-project to go in there

with CDPATH you simply do

cd fmp (press tab and autocomplete will fill in the rest)

(not my original idea, got it From Rob Pike https://twitter.com/rob_pike/status/467367507305574400 )


Thanks

Simon Ritchie

unread,
Sep 24, 2016, 7:30:29 AM9/24/16
to golang-nuts, leon.j...@gmail.com
This could be a bit better explained on the golang website. 

First, note that there are potentially three environment variables involved: PATH; GOROOT and GOPATH.

The Getting Started guide (https://golang.org/doc/install#install) gives quite a lot of help, and you should read that thoroughly.  Firstly it says:

"The Go binary distributions assume they will be installed in /usr/local/go (or c:\Go under Windows), but it is possible to install the Go tools to a different location. In this case you must set the GOROOT environment variable to point to the directory in which it was installed."

So, you either install the tools in the default location or you set GOROOT.

If you have this include:

    include ("log")

Then the compiler can find the log package in either the default location or the one in GOROOT. 

My Go installation is in the default /usr/local/go, so my log package is in /usr/local/go/pkg/linux_amd64/log.a.  The source code is in /usr/local/go/src/log.

I set up my .profile to put /usr/local/go/bin into my PATH, so I can run the go tools.

Assume that I set the GOPATH variable like so

    export GOPATH="/home/simon/gocode:/home/simon/goprojects/films"

and I run

    go get github.com/emicklei/go-restful

This fetches the go-restful package and puts it into THE FIRST directory in the GOPATH.  So now I have

    /home/simon/gocode/src/github.com/emicklei/go-restful/

containing the source code and

    /home/simon/gocode/pkg/linux_amd64/github.com/emicklei/go-restful.a

containing the compiled object

I can now have this include

    include github.com/emicklei/go-restful

My own project lives in the second directory in the GOPATH - /home/simon/goprojects/films.  As  Volker explained, this should contain a directory src containing the source code.  When I run the compiler, it will create directories pkg and bin.

The Getting Started guide goes on to explain how to create source code that you can commit to the github.  "Next, make the directories src/github.com/user/hello inside your workspace (if you use GitHub, substitute your user name for user), and inside the hello directory create a file named hello.go"

In fact, if you are going to commit your project to the github, then you should create an empty project on github.com first and then clone it on your machine.  This creates a directory for you, an empty git repository.  It contains a "hidden" directory .git containing all the information that git needs to work.  When you have everything working, you can commit your files and push them to the github.

For example, I have a github account goblimey and I used the github.com website to create a project called films.  I then did this on my machine:
 
    cd /home/simon
    mkdir goprojects
    cd goprojects
    clone https://github.com/goblimey/films      # creates a directory films

    export GOPATH="/home/simon/gocode:/home/simon/goprojects/films"
    export PATH=$PATH:/home/simon/gocode/bin:/home/simon/goprojects/films/bin

So now I have a github repository in the directory films and the two bin directories are in my PATH.  One of the bin directories doesn't exist yet, but the first compilation will create it.

In the films directory I create src/github.com/goblimey/films.  My source code lives in there. 

So, I end up with /home/simon/goprojects/films/src/github.com/goblimey/films containing my source code.

To install it, I use this command (which I can run from any directory)

    go install github.com/goblimey/films

This looks through the directories in my GOPATH looking for one that contains src/github.com/goblimey/films and compiles the contents.

The result goes into /home/simon/goprojects/films/pkg and /home/simon/goprojects/films/bin.

Given any include, the compiler will search for it in either the default compiler location or GOROOT, plus the directories in GOPATH.  In my case, that will be:

    /usr/local/go/pkg
    /home/simon/gocode/pkg/linux_amd64
    /home/simon/goprojects/films/pkg/linux_amd64

Once I have everything working, I commit the result to the github BUT not the bin or pkg directories.  Only the src directory.  That gives enough information for somebody to clone my project and build it themselves.  Their bin and pkg directories will be different from mine, so we don't want them in the repository.  (In general, if file B is created from file A, put A into the repository but not B.)

The scheme I use allows me to have Go projects in different directories.  That requires a different GOPATH setting for each one, so I create a script in each project directory that sets up the GOPATH.

If you want to, you can put just a single directory in your GOPATH.  In that case, it will contain everything that you fetch using go get and everything that you create yourself.  I prefer to keep things separate.

To sum up, this issue is really quite a complicated.  You need to read the documentation carefully, but there are gaps in it, and some of the issues don't crop up until you are quite a long way down the track.  I'm not surprised that people get confused.



 
Reply all
Reply to author
Forward
0 new messages