有关$ GOPATH的一些问题

I'm a new golang developer and I wonder why $GOPATH environment variable is needed to be set at the root of my project.

If I'm working on several projects at the same time, I need to each time re-set the $GOPATH environment variable to point to a different location.

In my setup, I have $GOPATH set to /Users/Projects/go/lib. which is a generic directory for all of my golang projects.

Just to clarify: the projects data is placed in /Users/Projects/go/<Project Name>

If anyhow all $GOPATH is used for (as far as I know) is to install 3rd party libraries, isn't it safe to have one $GOPATH directory for all my projects, so all the required 3rd party libraries are installed in the same lib directory, and whenever I compile on of the projects it just uses the libs it requires.

Is this bad in practice? Why?

(Q2 2018:
Note that with the vgo project, GOPATH might end up being deprecated in favor of a project-based workflow. That would avoid the manual project-based GOPATH I was proposing below, two years ago)

With Go 1.11 (August 2018), GOPATH can be optional, with modules.

It is more and more supported with VSCode:


June 2016: You don't have to rely on only one GOPATH (ie one workspace).

My full GOPATH includes:

  • a global path (for all utilities like goimports), github.com/smartystreets/goconvey, ...), in $HOME/go for instance,
  • a local path (for my current project), where my local src, pkg and bin will be.

That is two paths:

export GOPATH=/path/to/myproject:$HOME/go

Isn't it safe to have one $GOPATH directory for all my projects, so all the required 3rd party libraries are installed in the same lib directory, and whenever I compile on of the projects it just uses the libs it requires.

Is this bad in practice? Why?

I don't like that practice, as different projects could require different version of the same library.
That is why I have one GOPATH per project, that my build script (versioned with the project) sets for me.

When I clone a go project of mine, I:

  • set my GOPATH to that go project (local path, where the third-party libraries I need for that project will be installed, and moved to a vendor folder),
  • make a symlink to that path <myproject>/src/<myproject> -> ../.., since GOPATH means go expects to find the sources of myproject in src/<apackage>.

That organization:

  • remains compatible with go get,
  • ensure any specific dependencies I need are installed by default in my project folder instead of being lost within the mass of global libraries/utilities present in the global GOPATH.

I have:

myproject
   mysource.go
   apackage
     othersource.go
   src
     myproject -> ../..
     vendor
        third-party packages

On Windows, a typical build script would be:

λ more b.bat
@echo off
setlocal EnableDelayedExpansion
if not defined GOROOT (
        echo Environment variable GOROOT must be defined, with %%GOROOT%%\bin\go.exe
        exit /b 1
)

set PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
set PATH=%PATH%;%GOROOT%/bin
set GOPATH=%~dp0;%HOME%/go

set prjname=%GOPATH:~0,-1%
for %%i in ("%prjname%") do set "prjname=%%~ni"
rem echo prjname='%prjname%'

if not exist src (
        mkdir src
)
if not exist src\%prjname% (
        mklink /J src\%prjname% %GOPATH%
)

pushd %~dp0
cd src\%prjname%
rem cd
go install
popd
endlocal

Anyone cloning my go project would simply type 'b'.