go: cmd/go: assume GOPATH=$HOME/go if not set

This proposal is a simplification of #12488.

In short, if the user has not set $GOPATH in their environment the go tool will default to a value of GOPATH=$HOME/gocode.


Rationale At the moment all the documentation we have says “you have to set a GOPATH”, then people get distracted and upset because they don’t understand why they have to do this.

By choosing a default GOPATH, we can make our documentation easier because we can say things like

$ go get github.com/foo/bar

will check out the github.com/foo/bar repo into $HOME/gocode/src/github.com/foo/bar.

We don’t need to distract newcomers with having to set an env var, all we need to do is put a little parenthetical note at the bottom of the page

$HOME/gocode is the default path to your go workspace. If you want to change this path, set the GOPATH variable to something of your choosing.

Compatibility This proposal only changes the experience for newcomers who have not chosen to set a $GOPATH variable. For anyone using Go 1.1-1.7 today, your experience will be unchanged as you are currently required to set $GOPATH.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 100
  • Comments: 137 (91 by maintainers)

Commits related to this issue

Most upvoted comments

How about $HOME/go (which is what I use).

Thumbs up here if you currently use GOPATH=$HOME

Thumbs up here if you currently use GOPATH=$HOME/gopath

$HOME/go it will be. There is no single best answer but this is short and sweet, and it can only be a problem to choose that name if $HOME/go already exists, which will only happy for experts who already have go installed and will understand GOPATH.

Thumbs up here if you currently use GOPATH=$HOME/gocode

update: I had a quick look at this and wrote some code already, will add some tests and send a change later today

How many people already use GOPATH=$HOME/gocode? It seems to me not many. That suggests it is the wrong default.

If this is for newcomers, I would advise against GOPATH=$HOME as that would create three directories in their home directory versus just one. I’m not keen on software that pollutes my home dir beyond necessary.

I tend to agree with Chris and Andrew: if there’s going to be a default GOPATH, it should be just $HOME/go, not gopath or gocode. Most users do not have a Go distribution checked out there (and everyone who does today already sets GOPATH, so this won’t bother them). The default needs to make sense for new users, not advanced ones, and for most users $HOME/go makes a lot of sense.

Jaana raised a concern about the go command getting confused if $HOME/go happens to be a Go distribution, but the go command already checks for accidental GOPATH=$GOROOT. It’s easy to check if that’s true when GOPATH is set implicitly as well. In fact it would also be easy to augment the check to look for, say, $HOME/go/src/cmd/go/alldocs.go, to avoid confusion even when GOROOT!=$HOME/go but $HOME/go does contain a Go distribution.

A default value ofGOPATH=$HOME/go SGTM, assuming we decide on a default and not an auto-sniffing approach.

Do we have any information about what most people do?

I use GOPATH=$HOME/gopath myself.

@krishnasrinivas @joegrasse There is no perfect solution. It’s easy to set GOPATH yourself, and I expect that that is what most people will do. The issue here is what we should do for the people who are newest to Go. These are not in general people who are installing their own Go distribution in custom locations. People who can figure out how to install Go in a custom location can figure out how to set GOPATH.

Think instead of a class of a new programmers who are using pre-installed Go distributions. We want them to be able to start writing Go code. We don’t want the first step to be “this is what an environment variable is. This is how you set one. Now set GOPATH to this.” Those steps have nothing to do with Go as such.

Again, there is no perfect solution, but it seems wise to pick something.

It does matter what the default is, because setting this default will essentially make it how everyone new to Go is working a few years from now.

The go command goes out of its way not to get confused when GOPATH=$GOROOT explicitly; I’m sure the same logic can be made to apply to am implicit setting as well. So I’m not too worried about smashing $HOME/go accidentally.

I still wonder if instead of a fixed default we should be auto-sniffing the current directory’s parents to figure out where GOPATH is. This is what many source tools do these days (for example, every version control system), so it’s a concept people would understand. And it doesn’t force them to use one directory name or to have only one GOPATH workspace. But we might as well have that discussion on the original issue.

The discussion on the value of the default took place a month ago. The decision on $HOME/go has been done and is already being implemented. Going back to that topic will only make the thread unbearably long.

@rsc I’d love that default to be GOPATH=$HOME because that means $GOPATH/bin will be in their path (on most linux distributions at least, not sure about darwin).

$GOPATH=$HOME/go is also a good choice and those who have the source of the compiler checked out there will have already set GOPATH=something else so there is no chance of conflict.

To be clear, I wasn’t trying to be flippant when I said

The point being, it matters less what the default is, just that there is one.

Rather trying to emphasise the goal of this proposal is to have the go tool use a default value for $GOPATH when one is not provided as this is a continual source of confusion and frustration for so many newcomers to the language.

I’m 👎 on auto sniffing because it fails a major use case, which is:

  1. I’ve installed Go, I didn’t actually read the Go installation docs, just followed what it said on the repo’s README that said brew install go
  2. I’ve run go get github.com/thething/theproject
  3. Now I get an error about not setting $GOPATH. What is that? I just wanted to run this program that someone tweeted about!

@freeformz,

$HOME/go is conflicting with the path go source code (go.googlesource.com/go) is often checked out. It is bad that the community blessed this location as a default for GOPATH 😦 I worry if someone forgets to set their GOPATH and runs the go tool, it will mess their current development directory.

@ianlancetaylor GOPATH=$HOME/gopath is a better default than GOPATH=$HOME/go because of the aforementioned reasons.

I’m against $HOME/go since sometimes you don’t have the root privilege and you need to install Go under your home directory. In such case, I think $HOME/go would be the best for GOROOT.

If you are on a Linux system, I would argue that the best place for $GOROOT might be in $HOME/.local/opt/go, not $HOME/go, depending on how you interpret the purpose of $HOME/.local, as only $HOME/.local/share (appearing to mirror /usr/local/share) is defined in the XDG Base directory spec: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html.

One could also argue that the best default for GOPATH / GOBIN (on Linux) should be: GOPATH=$XDG_DATA_HOME/go, or $HOME/.local/share/go GOBIN=$HOME/.local/bin

However that’s probably not the easiest to understand for new users? And it would also leave it unclear what’s the best approach on Windows. $HOME/go and $USERPROFILE/go does seem pragmatic.

The point being, it matters less what the default is, just that there is one.

My proposed behavior for this change:

Environment variables

  • If GOPATH is set the tools behaves as it always has
  • Otherwise, we check the HOME (home for plan9, USERPROFILE for windows) environment variable.
    • If that env variable is not set then GOPATH will not be set either: this means that “go get” will fail with cannot download, $GOPATH not set.
> unset GOPATH
> unset HOME
> go env GOPATH
  • Otherwise GOPATH will be set as $HOME/go ($home/go, %USERPROFILE%\go).
> unset GOPATH
> go env GOPATH
/Users/campoy/go

GOPATH creation

Currently if $GOPATH doesn’t exist it is created when we execute go get import/path. This will not change.

The only change is that if $GOPATH is not set in the user environment (i.e. echo $GOPATH displays no value) an extra check is performed to make sure the default value is acceptable:

  • if GOPATH is not set and no default value was created: the command will fail
> unset GOPATH
> unset HOME
> go get github.com/golang/example/hello
package github.com/golang/example/hello: cannot download, $GOPATH not set. For more details see: 'go help gopath'
👎
  • if the default $GOPATH doesn’t exist a warning will be displayed explaining that the directory was created, pointing to go help gopath for more info.
> unset GOPATH
> go get github.com/golang/example/hello
warning: GOPATH is not set, creating directory /Users/campoy/go. See 'go help gopath' for more information
👍
  • if the default $GOPATH exists:
    • and it is not a directory: the command will fail (as it did before)
> unset GOPATH
> touch ~/go
> go get github.com/golang/example/hello
package github.com/golang/example/hello: can't use GOPATH at /Users/campoy/go: it is not a directory
👎
  • and it is either an empty directory or a directory that has a subdirectory named src the command will succeed (no warnings)
> unset GOPATH
> mkdir ~/go
> go get github.com/golang/example/hello
👍
> unset GOPATH
> mkdir -p ~/go/src
> touch ~/go/others
> go get github.com/golang/example/hello
👍
  • and it is a non empty directory without a subdirectory named src the command will fail
> unset GOPATH
> mkdir ~/go
> touch ~/go/others
> go get github.com/golang/example/hello
package github.com/golang/example/hello: can't use GOPATH at /Users/campoy/go: it is not empty, and no 'src' was found
👎

So only a new warning is included whenever a directory is created using a default GOPATH.

If this is to make easier for people who start with Go for first time, let it be something like the current path:

GOPATH=$(pwd)

Setting export GOPATH=$(pwd) makes it easy for switching between projects

@joegrasse @krishnasrinivas Take a look at “Installing to a custom location”.

If you are untarring to anywhere other than /usr/local/go – for reasons of permissions or otherwise – it becomes necessary to set GOROOT as well, or compile from source.

As long as that is the case, there’s no benefit in using $HOME/gopath, etc. over the proposed $HOME/go.

Let’s please leave the use of GOPATH to find support files out of this discussion.

(GOPATH is meant to be a compile-time setting, not a run-time one. I know that people blur these sometimes and use GOPATH to find associated files at run-time, but I don’t think we should encourage that or make it easier to do. We need a better story for support files in general, but that should be a separate issue.)

Why auto set GOPATH, why not raise warning with good info how to set it if GOPATH not exists ?

The problem isn’t that people don’t know how to set an environment variable (for the most part), it’s that even if you do it feels poor to have to jump through hoops to get started using Go. Being able to use Go out of the box with sane defaults as soon as it’s installed makes the experience as seamless as possible, and means more people are likely to actually try Go after downloading it, instead of hitting a roadblock, losing their momentum, and deciding it’s not worth messing with.

I’m using $HOME/gocode as my GOPATH. I’m against $HOME/go since sometimes you don’t have the root privilege and you need to install Go under your home directory. In such case, I think $HOME/go would be the best for GOROOT. So we should use something different from $HOME/go as GOPATH.

Auto-detection is fraught with danger. I started prototyping this a while back, but it added significant complexity both to the go tool and the user experience.

I’m not in the loop of what’s been happening with the package management working group, but I can imagine a not-too-distant future where GOPATH is eliminated entirely.

That said, even if GOPATH does disappear some time in the near future, there may still be value in setting a default. If we do think GOPATH is likely to disappear, it doesn’t matter too much what we set it to.

From what I read above, there is some consensus that:

  1. As a default, GOPATH=$HOME is too invasive.
  2. The default should include the string go somewhere (likely as a prefix).

I’m not worried about GOPATH being a clone of the main go repo (i.e., GOPATH == GOROOT). People checking out the go repo are likely to have a GOPATH set. The go tool would detect the conflict anyway, as it does today.

With that in mind, the most succinct default would be $HOME/go, which I think is quite reasonable.

Today, when GOPATH is set, the necessary directories are created, unconditionally, as needed.

Thumbs up here if you currently use GOPATH=$HOME/.go

Sorry to spam… After doing some googling… I think “go get” should just prompt the user saying “No GOPATH has been set… Would you like to use the current working directory as your temporary GOPATH?” (Yes/No)

I think a systemwide GOPATH is a non-starter because of permissions issues.

Please, please let’s not let this thread turn into a discussion of canonical Linux path names and storage locations. It is not productive, and I feel this discussion has already strayed pretty far from Dave Cheney’s originally post.

I’m also not sure the actual absolute location matters that much, I think all this thread really needs to decide is “do we want a default Gopath?” (sounds like that’s a more-or-less overwhelming yes) and “should it be shared systemwide, or local to the user” (so far most discussion has been about local). After that, whomever implements can pick $HOME/gocode or $HOME/go or /usr/share/go/ or whatever they desire that seems reasonable to whomever reviews the PR, and things will probably continue to be pretty okay.

I like $HOME/gopath. It says what it is. The first result on Google for “gopath” is the right page.

@davecheney

default to a value of GOPATH=$HOME/gocode

There is no default HOME variable on Windows. What do you propose to do on Windows?

I’d love that default to be GOPATH=$HOME because that means $GOPATH/bin will be in their path

I am always worried about having $GOPATH/bin in my PATH. go get installs other people’s programs there. Do we really want new Go user installing random programs from the Internet somewhere in their PATH?

Alex

Voting started: https://twitter.com/golang/status/781189567437164544

On Wed, Sep 28, 2016, 10:51 AM Edward Muller notifications@github.com wrote:

How about $HOME/go (which is what I use).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/golang/go/issues/17262#issuecomment-250244110, or mute the thread https://github.com/notifications/unsubscribe-auth/ACIkDJ83L5fXByqw-NEQ11JxKPGv_iQkks5quqkXgaJpZM4KI0I2 .

I have mixed feelings on this, but my prevailing sentiment (as someone who has set $GOPATH) is that go get behavior should be “deterministic” and always install things under $GOPATH – a consistent and well-documented destination.

Even though I’m unaffected by this change, it feels weird that go get will download things to different locations depending on what the working directory is when the command is issued. I’m aware this is what wget, npm install, and other tools do, but it feels like a departure from the idea of a consistent $GOPATH value (which is how I interpreted the spirit of this change).

If this is beyond the scope of this issue, I’d propose simply exiting and outputting an error if $HOME is actually unset.

@robpike did you consider also my alternative proposal in #17271? I would like to understand why this proposal was deemed better

Thank you for the design sketch.

  1. Since we’ve now established that GOPATH is only going to be created during ‘go get’, let’s only print messages if the -v flag is given, consistent with the rest of ‘go get -v’ behavior.

  2. If the directory is created, the message should be at most

    created GOPATH=/users/campoy/go; see ‘go help gopath’

It’s not a warning: warnings are bad. On the other hand if the create fails then you might well want to print

go: creating GOPATH=/users/campoy/go: %v

Both of those messages can be printed regardless of whether GOPATH is inferred or set explicitly.

  1. The heuristics about empty directory and having a src subdirectory are too complex. Worse, they are addressing hypothetical problems, and hypotheticals are very difficult to design for. Better to have simpler, more predictable behavior. To start, I think it makes sense not to have any rules, until there are concrete examples of actual problems. There will be time for people to report problems during the betas and release candidates. Let’s just set GOPATH=$HOME/go (provided $HOME is set).

Edit: pretend that Github markdown didn’t completely screw this up.

@einthusan I feel like it’s pretty well-documented on https://golang.org/doc/code.html#GOPATH, but I don’t know how many people getting started with Go actually read this page.

@RalphCorderoy please understand the goal of this change is to make it easier for new Go users – this isn’t you – you already have $GOPATH set, because you have to with every version of Go from 1.1 onwards. The overlap between go-the-game users and potential go-the-programming-language users is very very small. I don’t think there will be an issue.

I’d be definitely happy to work on this.

If the target users for this change is only those that just wanted to install a new program written in Go, and not those that actually want to write Go, then what about we make go get cloning in a per-user directory in $TMPDIR, and leave the binary at $PWD if $GOPATH is not set? (Obviously this only makes sense for go get import.path/for/a/command, if it’s not a command, go get should fail without $GOPATH being set)

For the outsider, this makes much sense, just like wget a file.

Once the user wants to start writing Go code, they should learn how to set GOPATH properly.

@hnakamur Back when I installed Go manually (now using Ubuntu Make), I put it in $HOME/bin/go-${go_version} (with a symlink from $HOME/bin/go to $HOME/bin/go-${version}/bin/go, so I didn’t have to edit my $PATH)

But, given that Windows installer already installs Go into C:\go, C:\gocode for GOPATH is at least consistent.

GOPATH should not be provided for each users? To be the same as UNIX, %USERPROFILE%\gocode, I guess.

@rakyll to each their own, just wanted to indicate what I and many others use. go.googlesource.com/go is checked out in /usr/local/go.git on my system.

See also : http://go-talks.appspot.com/github.com/freeformz/talks/20160712_gophercon/talk.slide#7

$HOME: 8.9% $HOME/go: 50.6% Other : 40.5%

I really wish I had split out more options for this one.

“gocode” will have search engine and other confusion with the popular tool github.com/nsf/gocode.

@cescoferraro that’s a question for the maintainers of that image. Despite it being labelled as “official”, that project is not affiliated with Go.

@RalphCorderoy The situation you’re describing is rare, and anyone running shell commands from a random website shouldn’t have expectations that their disks won’t be wiped, let alone some files downloaded and shuffled around in an eponymous directory. (Edit: Consider Wine auto-creating and modifying .wine in the user’s home directory. What if the user has something else there? After all, “wine” is a term we use for a particular beverage.)

The naming collision between “Go” the language and “Go” the board game is certainly understood and well known. The filesystem is a shared resource, collisions happen and are inevitable.

@RalphCorderoy I’m think the amount of care and double underpants being engineered into CL 32019 is more than sufficient for the potential inconvenience to the small set of game-of-go-programmers who have not used Go before version 1.8 and have not set GOPATH and also are beginning to learn Go, the language.

The go tool isn’t going to delete or corrupt any non go code it comes across, you’ll just get a slightly confusing message in a few situations. To explain this, the go tool will not build Go source at the top of $GOPATH/src because that code is not within an importable package. Additionally, the other goal of this change is to make it easier to go get some code by providing a default location to download source to, so if there was the-game-of-go source code in ~/go/src, the chances of it conflicting with a subdirectory derived from a go gettable repository are very remote, and even if that were to happen, either the go tool or git would crap out before any data was altered.

I think that the situation you are concerned about is very unlikely, and further mitigated by the explanation above.

I vote $HOME/golang

Thanks.

Initial documentation could assume the default and not mention environment variables at all.

SGTM

There are two types of Go users:

  • Users who just go-get existing packages
  • Users who are Go developers

Default GOPATH is fixing the case for the first group. We still can keep GOPATH-related instructions around for the developers-facing docs. The installation shouldn’t have to mention setting GOPATH at all anymore or we can have an appendix as @davecheney mentions.

The system wide path is, for better or for worse, GOROOT, which distros like debian are using to install “system wide” packages, for better or for worse.

A system wide GOPATH is out of scope of this proposal, this proposal recommends a path derived from value of the logged in user.

On Tue, 4 Oct 2016, 08:52 Andrew Gerrand notifications@github.com wrote:

I think a systemwide GOPATH is a non-starter because of permissions issues.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/golang/go/issues/17262#issuecomment-251238251, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAcA2kwyq0Iuidk0ygsGzqVKGLkKBR9ks5qwXkDgaJpZM4KI0I2 .

I use $HOME for my GOPATH. Why auto set GOPATH, why not raise warning with good info how to set it if GOPATH not exists ?

I assume there is some notion of a base path where documents and settings are stored.

I don’t know of such thing. Perhaps other Windows users will comment here.

If no such path exists, assume C:/gocode.

You want C:\gocode instead. Putting things in the root of C:\ does not sounds right to me. Would you recommend GOPATH to be set to /gocode on Linux? But, given that Windows installer already installs Go into C:\go, C:\gocode for GOPATH is at least consistent.

Alex

I’m not an experienced windows user, but I assume there is some notion of a base path where documents and settings are stored. For the purpose of this discussion assume that I’m talking about that path in the context of windows users.

If no such path exists, assume C:/gocode.

Wrt to my comment on GOPATH=$HOME, while this is and will continue to be my personal preference, I recognise that this is a contentious option for a default value and as such did not suggest it as the proposed value.

The go command goes out of its way not to get confused when GOPATH=$GOROOT explicitly; I’m sure the same logic can be made to apply to am implicit setting as well.

Sounds great.

not sure about darwin

Not on darwin.