'Some questions regarding $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?



Solution 1:[1]

(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'.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1