What is the reason to have GOPATH set to my workspace? - go

I read everywhere that my GOPATH must be set to my workspace. If I do that and use go get to get packages from for example GitHub, they are all added to my workspace though, which I don't find particularly useful because it clutters my workspace. In my workspace I expect to find MY code and my code only.
So I now have my own repos in ~/repos/go and left my GOPATH to be the default ~/go. This works perfect. All libraries I import live in ~/go, which keeps my own workplace ~/repos/go nice and clean. This works great for me, so I'm not sure why this is not the recommended way of working.
Am I missing something? Are there things I break or are functionalities not working in this way?
Edit
To explain why my question is different from this question: I know what GOPATH does (define a place to put packages when using go get and a place to import packages from), but I was unaware of why you need to have the public code in the same place as your own code. Turns out there is no need for it, as explained by #peterSO in the (excellent) answer I accepted below.

go help gopath
Go searches each directory listed in GOPATH to find source code, but
new packages are always downloaded into the first directory in the
list.
$GOPATH is a directory list. For example, on Linux,
export GOPATH=$HOME/gopublic:$HOME/goprivate
go get places all downloads in the first directory in the list: $HOME/gopublic. Put all your packages in the second directory in the list: $HOME/goprivate.

GOPATH is a default directory that the golang toolchain looks at when you're attempting to compile code. It's not technically 100% necessary to set a custom one, as if I recall correctly, it defaults to ~/go/.
As peterSO said above, GOPATH is a list and puts packages into the first entry.

Related

What is the correct setting for GOPATH?

I was trying to follow a tutorial on using aws with go. When I gave the command "go get github.com/aws/aws-sdk-go/aws", I still got failure to import. I was left wondering if the "go get" succeeded or not.
Following the guidance provided in the answers here, I updated my GOPATH variable and now the import succeeds.
Your hello.go should start something like this:
package main
import (
"github.com/aws/aws-sdk-go/aws"
)
See this example in the playground. So when importing a remote module use the full path in the import statement.
Re another question you asked in the comments (and I mentioned in comments to another of your questions) - go mod init initialises a module. See this article for information. When using modules, GOPATH is no longer used for resolving imports (see this article). So basically GOPATHis the old way of doing things; go modules is the new way (it solves a lot of issues but having the two approaches can be confusing to someone new to the language because some tutorials assume GOPATH and others use modules).
For completeness you have other questions about environmental variables. I think this may be due to a misunderstanding about how these work. When you enter export GOPATH=XXX in a terminal session that will update the environment within that session (that is that terminal window only; it will not have any impact on any other sessions you have open, including vscode). If you want to set a system wide environmental variable then you need to update a configuration file (often ~/.bashrc but this depends upon your OS see this article for info). After doing that restart the applications (or ideally youre PC) to pick up the new setting.
When you run go get github.com/aws/aws-sdk-go/aws; go tool will download the package into $GOPATH/src/github.com/aws/aws-sdk-go/aws directory.
That is why you need to import package by its full name (which is same as path to files under $GOPATH/src directory:
import "github.com/aws/aws-sdk-go/aws"
You can find more about how source code is organized under GOPATH and how imports work here and specifically about remote (github) imports here.
NOTE: GOPATH resolution works only when your project doesn't use modules (you don't have go.mod file). If you're following a tutorial and it doesn't mention use of modules above should work fine.

What is the best local structure for Go open source repository development?

I'm trying to debug Go implementation of ethereum(link), because my core interest is in developing new consensus algorithm (i.e. modify the open source Go code from github).
However, I'm having problem with the location/path of the source code. When I put the folder(i.e. go-ethereum) outside of the $GOPATH and then try to compile&debug geth(go-ethereum/cmd/geth/main.go) it shows the following error: Use of internal package is not allowed.
From that error message, I figured out that the import github.com/ethereum/go-ethereum was not importing my source, and instead it was getting code from internet(like other libraries). Which of course is definitely what I shouldn't do when I'm trying to modify the github.com/ethereum/go-ethereum package code.
So, my workaround was to clone the source code into $GOPATH/src/github.com/ethereum/go-ethereum and followed this answer, and Goland IDE started compiling&debugging without error (wasn't able to go build ./cmd/geth/main.go though due to error undefined: configFileFlag...)
Thereby now I've got a working debugger that can debug with my source code modification, but this doesn't look like ideal source code structure.
The question is:
Is putting source code inside $GOPATH(because of internals) a proper approach? If so, what if I was using go-ethereum package from another project?(Fortunately I'm not, but I'm curious) Do I have to stash&revert changes I made to the code?
Yes, the folder structure you ended up with is the right one.
Code should be under $GOPATH/src as you describe.
But note that $GOPATH is not a fixed folder in your system, you can have multiple projects under different folders and change the value of $GOPATH accordingly depending what you are working on (or have multiple console terminals open, each with its own $GOPATH value).

Do all Go projects need to live below GOPATH? [duplicate]

This question already has answers here:
Can someone explain why GOPATH is convenient and how it should be used in general?
(3 answers)
Closed 4 years ago.
I am starting with Go and trying to get my head around GOPATH (and probably GOBIN).
When trying to fetch external libraries via go get I get the error
go get: no install location for directory D:\Seafile\dev-perso\domotiqueNG\services\dispatcher-go\src\dispatcher-go outside GOPATH
This error is apparently solved by having a project structure below $GOPATH/src.
Does this mean that all my Go programs must live there? If GOPATH is d:\hello then the projects bonjour and aurvoir really need to be in
d:\hello\src\bonjour
d:\hello\src\aurevoir
only ?
In this is the case how can I
split, say, personal and professional projects when the personal must stay at d:\home and professional at x:\work ?
have multilanguage projects where d:\home\domotique\dispatch is in Go, d:\home\domotique\whatever is in Python, and I have several such combos in d:\home?
You can actually have Go projects outside of GOPATH. However, some tools do not work well or do not work at all in this kind of situation. For example, goimports, which formats your code and add missing imports, will not be able to find packages that are outside of GOPATH. You'll have to write the imports manually using a relative path: ./path/to/your/package.
how can I split, say, personal and professional projects when the personal must stay at d:\home and professional at x:\work ?
You actually can have multiple Go workspaces (https://github.com/golang/go/wiki/GOPATH). You just need to set GOPATH to the list of their location joined with the list separator of your OS. e.g. on Linux it would look like this:
GOPATH="/home/nobody/perso:/home/nobody/work"
Though, I'm not sure how go and other tools such as dependency managers handle multiple workspaces.
When using the GOPATH you can make subdirectories in the /src folder, for example, adding both home and work directories. In fact, the Go project has an example of how to organize code. While packages need to be in their own folders, a folder itself in the GOPATH is not automatically a package.
If you'd rather not work within the confines of the GOPATH, you can change it to the path you do want to work in, or set it to your home directory.

how to manage GOPATH for multiple project directories

coming from a java and grails background, (and having written millions of lines of C 30 years ago), I cant see how go can be usable with a fixed gopath on windows.
installing go creates this structure
c:\users\me\go\scr
\pkg
\bin
As you will want to have many go projects it seems they have to be mixed together in the same src/kpg/bin dirs, polluting each other. e.g.
/src/project1/hello.go
/project2/hello.go
/pkg/xx
/bin/hello.exe
Which hello.go will hello.exe run?
Unless I am missing something fundamental, this seems crazy - all completely separate projects are expected to share the same package and bin dirs. It means you dont know which versions of which packages, and which exe files belong to which project, and there is presumably plenty of scope for conflicts. I would have expected a /src, /pkg and /bin for each separate go app (like java or grails or even C), and go path is completely redundant, it can be relative to the current project root (like in grails).
To make matters works, for work, we have to use a different directry, e.g.
d:\work\project3
\project4
\package5
\go_utility6
\go_utility7
So now we have a total of 6 separate directories where go progams live. It is not feasible to change the path every time you switch to working on a different project. I guess the other option is to add the 6 paths to the GOPATH. Presumably, all 7 go projects write to the same pkg and bin dir, which is going to be a disaster.
Is there a tenable solution to this situation (on windows at least)?
If we need to add a PATH to GOPATH for every project, what should the file structure be under each project?
E.g. uner xxx\go_utility6, which is a stand alone command line go app, what should the structure be? does there need to be a src dir in there somewhere? does this dir need gopath to point to it? does it need its own pkg, or should it use the c:\users\me\pkg dir?
UPDATE: When I posted this Go did not have modules support and we built and used a tool called vg. These days the recommended way to go is to use go modules.
I use vg for that, it takes care of keeping separate GOPATH paths per project and it switches automatically when you cd a project.
Your example "which hello.exe" should be used honestly makes not much sense. Two tools with the same name?
Even if both are, let's say, an api, your devops will be happier with more meaningful names.
The bin folder is used for 3rd party tools you install, you so not have to install your project binaries. Except they are tools, but then the name should be meaningful again.
You can get more information about the project structure here: https://golang.org/doc/code.html
Since go 1.8 supports a vendor folder below project folders, it is possible to break the original structure. (imho vendors were not maintainable before 1.8, yes that was crazy)
You might want to use a tool like direnv, which would support your desire to change GOPATH per project.
https://github.com/direnv/direnv
It also has some built in function for adding the current path to the GOPATH.
https://github.com/direnv/direnv/blob/master/stdlib.sh#L355:1
For example GoLang also supports handling multiple GOPATHs and per project GOPATHs. So direnv should also work properly.
In my company we have one go folder right next to our other projects.
Under go/src are our projects. No problem so far, since vendors are in the projects' vendor folders and committed.
The so far best dependency manager I would recommend for go is:
https://github.com/golang/dep
I hope that input helps.
With Go 1.11 Go Modules were introduced. You can use Go Modules to have Go projects outside the GOPATH directory.
Here is an example of how to configure a project using GoModules.

go get with multiple projects in workspace

In Go, the workspace contains the src, pkg and bin directories. How do I create multiple projects in the workspace, each with its own src, pkg, bin directories, such that I can 'go get' packages into the pkg directory of a particular project.
You probably do not need that. Let's forget also the word "workspace" it's probably only confusing you.
If you set your GOPATH environment variable that that's all you actually need to have multiple projects independently sitting on you hard disk.
For example, having export GOPATH="$HOME", and performing
$ go get github.com/foo/bar
$ go get github.com/baz/qux
Your directory tree will be
$GOPATH/pkg...
compiled packages
$GOPATH/src/github.com/foo/bar
bar.go
$GOPATH/src/github.com/baz/qux
qux.go
More details here. Note that it does talk about workspaces, but I still consider that fact very unfortunate. The earlier versions of that doc did not use nor define the concept and they were useful anyway. That's IMO a proof of it (the workspace) being redundant.
go get is not intended to be used that way.
all go get packages land in $GOPATH/* as described here: http://golang.org/doc/code.html#remote and there is no concept of separate workspaces.
If you really want several "workspaces": Have several entries in GOPATH (separated by ":" on unix).
(But most just keep everything under one GOPATH).
Remember that go get fetches packages only into your first GOPATH entry.
The other entries can be used as "seperate workspaces".

Resources