-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: cmd/go: automatically detect GOPATH #12488
Comments
/cc @jbuberel who was talking about this this morning. |
@adg thanks for raising this proposal. I thought it was going to be more along the lines of "lets have a default GOPATH value (and it might be $HOME)"
I like this, but I think there are still a number of edge case that have to be explained en rote. q. why do I need to make a sub directory, can't go just work in my current directory ? q. oh, ok, well I put my code in src/hello.go and it didn't work ! q. ok, so I put my code in gocode/hello.go and it didn't work, you told me src/ was special so I didn't use it q. ok, thanks for helping, that worked, but I have a question, why do I need all these directories, shouldn't Go be able to figure this out ? q. what's a package, i just wanted to try helloworld.go ?!? This is taken pretty much verbatim from my experiences having to justify the $PROJECT/src directory in gb. |
I'd like to suggest that any automatic strategy to compute GOPATH should work anywhere within $GOPATH, not just within $GOPATH/src. E.g., it should at least also work within $GOPATH/bin and $GOPATH/pkg. Easy variation of the proposed scheme is instead of looking for a parent directory named "src" (and then using its parent as GOPATH), look for a parent directory with a "src" child directory (and use the parent itself as GOPATH). Another option would be to add a new identifying file within the root directory. E.g., Bazel uses an empty file named "WORKSPACE" (see "Getting Started with Bazel") and Chromium's GN uses a file named ".gn" with config settings (see "What you need for a minimal GN build"). |
I think we don't need to support $GOPATH/bin and $GOPATH/pkg,
because I can't think of a reason why I'd in one of those directory
and still use go build/install/test. Just handle the common case looks
good to me.
I also don't like introducing a new file to mark GOPATH.
|
@davecheney I think at some point people need to learn about packages. I don't think we should design our entire build process around the very first new user experience. Can you suggest a way of avoiding this conversation that doesn't throw out everything we already have? (My gut reaction is "just tell them to put it in "src/hello" in the first place.") @mdempsky I concur with @minux - I have no idea why you would care about resolving $GOPATH inside Another consideration for this proposal is that it will theoretically break anyone that already has packages whose import paths have a |
👍 This change makes sense. I don't see what a default $GOPATH (for example at $HOME) would solve in terms of making it easier to get started with Go. I think if a user knows about $HOME (its significance) then he is proficient enough to setup a correct $GOPATH. |
@mdempsky I think the idea of "GOPATH is the parent of a directory called src/" works well.
Agreed.
I'll have to disagree with you to some degree there 😄
I think I probably conflated a number of things in my response. From my experience there are several common pain points for newcomers when they see a path like
Maybe this is just a matter of introducing the terms in order. Something like There are two pieces of information you need to know to write Go code. The first is all Go code must live inside a workspace, we call that GOPATH. A GOPATH workspaces is any directory that contains the following three directories
So, As mentioned above, all the Go code you write must be arranged into packages. What is a package ? A package is just a directory. The name of the directory must match the name of the Putting these two pieces of knowledge together, if you want to write a program called This explanation obviously trades off some degree of accuracy to avoid getting bogged down in the details, please don't beat me up for this. |
What about That could initialize the path, create an directory When the (Linux- )Distributions could then also easily integrate (Appropriate defaults for e.g. Windows are left out for the moment but can be easily added) |
Is there a reason why we can't just build our default gopath in $GOROOT? Just add a $GOROOT/usr/$USER directory which is populated with it's own /bin, /src, /pkg and auto generated by the go tool. Its one thing to have the developer explicitly state where they specify $GOPATH resides on their system, its another to allow go to automatically dig around for one. |
I think the original proposal is fine for those who understand package and workspace structure but I don't believe it to be helpful to new Go users as was suggested. The problem is that it's very likely that new Go users will be creating test directories within existing directory trees that contain code of different languages -- and |
The go tool doesn't care if you have scripts/source written in other programming languages stored inside the same directory it found a set of *.go files in. It only cares that each declared package is confined within its own directory inside "$GOPATH/src". I "get" what @adg is saying. Ideally when you use the command I mean it definitely could work. It's just a really hooky programming environment convention if you ask me. It doesn't seem like it would always play nicely with Unix's file system security model either. (you develop your pkg in /usr/src, go installs executable in /usr/bin, which could bring about potential issues like system util name conflicts, or confused package managers, etc etc. Personally, I think @adg's proposal makes the go tool far too "magic wand"-ey, for the amount of convenience the language would gain from his proposal's implementation. |
My concern wasn't so much that the code of other languages would be an issue; only that |
Also if we did do this we would have to adopt a policy that each gopath would be isolated from each other's view unless GOPATH has been explicitly set. The reason being the fact that the go tool can't resolve a lookup path precedence ambiguity with out a directorial cue from the user that expresses the preference of their intent. |
What if $ go create workspace /home/tyler/myworkspace Then from anywhere you could do something like: $ go myworkspace build Maybe allow for a default or an active workspace: $ go active workspace myworkspace With an active workspace set you could simply do: $ go build The workspace name would be derived from the path passed at creation and could be referenced as simply. To facilitate this, you’d need to allow for a GOCONF environment variable to point to a location where a simple config file (containing workspace names and GOPATHs for each) could be written/read by the tool and at that point perhaps the complexity of the situation is just the same; Thoughts? |
I was also thinking about the idea for a go "workspace" project container object that essentially gives users one last degree of expressing package addressability. You wouldn't have to manually create, set, manage, and/or mess with them in any explicit way really. Rather the workspace mechanism would work by walking up the tree until we find ourselves inside of a "src" directory. Once there we "cd .." into the parent base dir where we ideally want to set up the gopath we associate with the pkg were building. Since that parent base directory must have an identifier, we can use it to declare a workspace context for that GOPATH. Syntactically the "workspace" identifier is treated just like a top level domain in all its usage contexts. For example if we wanted to call an executable that is in a specific $GOPATH/bin, we can just call In the context of it's import path string, it would be just a top level domain. Then in $GOROOT, go get will fetch and install to $GOROOT/users/$USER/$workspace/src/path/2/mypkg In the case that the top level domain is attachted to say github.com. We can just use the top level domain syntax to allude to a sub branch and/or tagged commit. And just create the workspace context name by appending the pkgname in front of the top level domain. So lets say we have import "v2.github.com/mortdeus/mypkg", the go get tool will see the v2, then the github.com, then the user name, and then the pkgname. Go get will resolve this to the directory $GOROOT/users/mortdeus/mypkg.v2/src/github.com/mortdeus/mypkg Then if we have a few executables called say mypkg/server, mypkg/client, mypkg/shell, mypkg/main Idk its just an idea. |
oh and in the case where we have a set of workspace ambiguity where we have say $GOROOT/users/{me | you}/gopkg/src/github.com/{my|your}/gopkg Obviously we have a conflict here regarding which "gopkg" executables are tied to the globally resolved generic "gopkg" workspace identifier as far as the go tool is concerned. The best way I can think of resolving this is to have a $GOROOT/users/mortdeus/bin that links to the workspace's executables we prefer to be called in the case of a naming conflict. |
A solution could be to say that the GOPATH is the parent of the top (instead of the bottom) src directory in the current directory. So, for example, when running go install from /home/user/src/github.com/project/src/package1, GOPATH would be set to /home/user. I think it is more unlikely to break something this way and with the right wording it is not more complicated (I am assuming the fraction of users with GOPATHs inside src directories is neglegible). For new users, I think the most important point is showing a sensible error message when trying to build a package outside of a GOPATH (or with this proposal, outside of a src directory). |
shouldn't it be something like |
I like @adg's proposal at the beginning of this issue of determining the GOPATH from the current working directory if the environment variable is not set. There are several other interesting ideas proposed here, like a default GOPATH and a go init subcommand, that are compatible with the original proposal. They could be done instead of or as well as automatically detecting the GOPATH. Are any of them arguments against determining the GOPATH from the current working directory? If they are complementary they can be considered separately. If they are arguments against @adg's original proposal, I think it would be helpful to frame them as such. |
In my opinion auto-detecting GOPATH via As a multiple workspace and |
@adg's proposal would be a nice improvement to the tool chain. It doesn't change anything when GOPATH is already set, and when it's not, it simplifies the workflow. Many tools like git, hg or Node/npm already successfully implement a similar behaviour. |
I really like the idea of auto-detecting GOPATH. I've been thinking about how to do this ever since I saw that @davecheney had done the equivalent in gb. I'm not as sure about how. Finding Then there's the problem that any directory-based detection fails when you're outside the directory. You might be in $HOME or $HOME/bin and realize you need a command and run "go get that/command" and it fails because you're not in the src tree. That's annoying. @davecheney's other points based on experience with gb are interesting too. Counter-proposal, as suggested by Dave: If GOPATH is not set, it defaults to the user's home directory (aka $HOME on Unix, $USERPROFILE on Windows, $home on Plan 9). The counter-proposal is not as flexible, but it's the suggested setting, it works outside the source tree, and it can't ever be confused by an inadvertently named parent directory. I put the counter-proposal here mainly to play devil's advocate: if we're going to autodetect, we should make sure we are considering all the possible ways, not just one, and then pick the best. As I go through the details, though, I'm starting to like default $HOME better than default magic search based on current directory. |
@rsc thanks for your comments. re: finding the wrong re: not being able to do 'go $CMD' anywhere on the filesystem is quite a With that said, the place where this will bite will be In the face of this, defaulting $GOPATH to $HOME would a. solve all of the issues above And, as you say, if people don't like the default, all they have to do is On Sat, Oct 24, 2015 at 2:54 PM, Russ Cox [email protected] wrote:
|
Hello, What is the status of this proposal? If it's stalled, I'd like to make my own, simpler, proposal along the lines of #12488 (comment). |
@davecheney I'm happy for you to make a counterproposal here, unless it is not about automatically detecting GOPATHs at all. |
TL;DR - I want to propose that GOPATH defaults to $HOME. On Mon, Sep 26, 2016 at 9:35 AM, Andrew Gerrand [email protected]
|
@davecheney, not until we nuke the "pkg" directory. I'd like to add proper caching to |
@branfitz is that because I suggested GOPATH=$HOME, if I suggested an On Mon, Sep 26, 2016 at 9:53 AM, Brad Fitzpatrick [email protected]
|
@davecheney GOPATH defaulting to home won't fix the "complex CI build" issue, but is nice. If pkg is removed at some point, all we'll need will be to have a flag to specify the position of the CWD in the go import tree. |
If you don't want GOPATH=$HOME then all you have to do is set $GOPATH On Mon, Sep 26, 2016 at 10:00 AM, Mikaël Cluseau [email protected]
|
I wouldn't object, at least. But I (and I think others) would object to Go automatically creating a $HOME/pkg dumping ground, surprising users. |
@bradfitz is there a plan to do away with pkg? It does not seem easy to me, it is an important performance optimization, especially if you are importing cgo packages. What if an unset GOPATH implied pkg being somewhere off in a temp file system? |
To be clear, I want GOPATH to be a default, I don't care what the default On Mon, Sep 26, 2016 at 10:04 AM, Brad Fitzpatrick <[email protected]
|
On 09/26/2016 11:03 AM, Dave Cheney wrote:
I agree, I just want to underline the path that put me in this thread, |
The former. The latter may have to set an GOPATH environment variable, this On Fri, Dec 11, 2015 at 10:30 AM, Dmitri Shuralyov <[email protected]
|
@MikaelCluseau in that case nothing changes, the CI user will have to set GOPATH, just as they do today. |
I'd say this is out of scope. Various CI tools like travis have worked around the fact that the checkout of the go project is not the root of the workspace. My proposal to set a default GOPATH does not change this. |
On 09/26/2016 11:10 AM, Dave Cheney wrote:
|
Yes. That is #4719. It will still exist, but instead of being at $GOPATH/pkg, it'll be at a OS- and user-specific cache directory, and it'll be a cache of outputs from actions of content-addressable inputs. Which means |
This proposal only changes the experience for newcomers who have not chosen to set a GOPATH variable. At the moment all the documentation 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 documentatation easier because we can say things like
will check out the 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
|
I foresee problems here though when you e.g. start using a new shell and in the old situation the error message would inform you that it's not set up correctly yet. With your proposal you would silently get the code checked out and duplicated, and you end up with a mess, if you don't use the same GOPATH. in my proposal that doesn't happen, because any new shell will automatically pick up the same old directory, it works when you migrate to a new system and will gently put the new users through it. |
Also, if you add this stuff to an independent tool, you can backport it to old versions where necessary. |
@rsc as the proposal arbitrator would you welcome a proposal to provide a default GOPATH if one is not explicitly set in the environment? |
I think we're going with #17262. |
Setting up a workspace/GOPATH is one of the big hurdles for new Go users. And maintaining (switching between) several workspaces is a common work flow for some Go developers.
This proposal is to make the GOPATH environment variable optional, and to have the go tool detect the GOPATH root on invocation. It would to this by walking up the tree from the cwd to find a directory named
src
, and settingGOPATH
to the parent of that directory.For new users, the getting started experience is something like:
or to install something else:
Thoughts?
The text was updated successfully, but these errors were encountered: