-
Notifications
You must be signed in to change notification settings - Fork 17.6k
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
cmd/go: modify the Go toolchain to work without GOPATH #17271
Comments
If you don't want to use But seriously, in my experience the problem newcomers have with Using the go tool does have a learning curve, that is undeniable, but I believe the go tool, and the conventions of laying out source in the My proposal in #17262 seeks to defer the additional cognitive load of choosing a |
I respectfully disagree. I never had somebody complain to me that choosing
My proposal removes all four hurdles above; it erases the whole cognitive load associated with Also, if we look at a modern Go application, with all its dependencies correctly vendored, I really can't see what |
But which import path supposed to use for the project's packages if there is no GOPATH? |
The GOPATH issue has been a real stumbling block. We have multiple projects for multiple clients, each project uses a multitude of different languages and frameworks. They are all in different directories, different volumes etc.. We want all code associated with a specific project to be separately managed. It has been very difficult to see how the GOPATH architecture supports this. It is certainly not documented in the standard "getting started" information. |
@dmage I think it should just be "." or whatever it is called the top-level path in the import hierarchy. This would mean that, to work without GOPATH, projects including sub-packages will have to refer to them with a relative path like "./foo". I think it's a reasonable compromise for projects that wish to build without GOPATH. (a possibly crazy idea is to also use canonical import path for this, that is a way of teaching the Go toolchain the path of the current project being built in a no-GOPATH scenario) |
As I work on several projects using Go alongside otherside programming languages, this is exactly my experience. |
Since #17262 is going forward, the "if GOPATH isn't set, use '.'" can no longer apply. But a slight change to "if outside the GOPATH, use '.'" would do the trick - mimicking gb's behaviour and allowing people to just download/copy a piece of code and compile it then and there (possibly with a friendly warning message, that the user is outside the GOPATH). Then again, this sounds an awful like #12488, which was declined. |
Regarding the resolution of #17262: while this proposal takes advantage of an unset |
Well, yes, I guess it's possible to adapt a part of this proposal with a default |
I have had to deal with the problem that this proposal offers to solve. That being, making it easy for the non-go developers at my company to be able to check out a Go project to a random location and build it. Because I can't expect every developer to have a GOPATH set up, or to clone to a specific location, I have needed to design Go logic into our waf-based build system. This has to try and do extra smarts such as forming a GOPATH on the fly if it can. Telling them to use gb is not an option for multiple reasons. They would need a special tool as a non go developer, and gb takes its own approach to the vendor directory (last I checked) in having vs not having a src subdirectory. It would be fantastic if the standard go tool could offer sane default behavior for trying to build a project that is outside gopath, before failing. If it at least tried to assume the project is self contained with a vendor directory, it would have a chance to build. Isn't this following the same goal as #17262 in having default behavior that makes it easier for beginners? |
The go tool requires GOPATH, it's built into its design and backed by its What is it specifically that you don't like about gb? It seems like its On Wed, 26 Oct 2016, 05:42 Justin Israel notifications@github.com wrote:
|
It is the very fact that gb diverges from the official standard, that being the go tool. Problem is that I cannot force a developer to build their Go projects with gb, so that I can then assume I can use gb to build it later, in our build system layer. The most likely path is that a developer will use the official go tool and structure their project (including the vendor directory layout) to match. Then I have to make sure any other developer can clone that project and build it, regardless of where they clone it. To use gb, I would have to make it a standard that everyone follows. |
On Wed, 26 Oct 2016, 06:26 Justin Israel notifications@github.com wrote:
The important thing for me when I built gb was the realisation that the go Problem is that I cannot force a developer to build their Go projects with
Yeah, but is it fair to say that it doesn't work for you, or them, Then I have to make sure any other developer can clone that project and
Gb is only for projects, applications that produce binaries. It has no —
|
I wouldn't say gb doesn't work on its own. Its more a case of gb not being able to be suggested as the solution to the problem being proposed here. I was just trying to make a case really for the go tool to adopt some of the concepts of gb, by making the zero value of the go tool more useful. The most common scenario would be that people are following the official Go project structures and expect projects to be able to be built with the go tool. So with that being said, it would be amazing if the go tool could cope with more situations and try harder to build before failing. Just like gb is only for projects, applications that produce binaries, the go tool could also try to ensure that an application can be built regardless of GOPATH not being set, if it can do so by assuming some defaults. |
Let's see how much of the problem is solved by automatic GOPATH=$HOME/go in Go 1.8 and revisit this in a release or two. |
@bradfitz I really don't see how an automatic GOPATH solves anything, this proposal is about the possible ability to do without the GOPATH. |
I understand the difference. Hey, listen, I don't want GOPATH either. But I'm also realistic about how fast things move. I'd love to be see it happen sooner than later. Personally I'd like something like git where the "go" command would walk up the tree, looking for a magic directory that's the GOPATH. In Git, that's the We also need to fix #4719 first and get rid of the $GOPATH/pkg directory entirely, making all build artifacts aggressively cached. That would fix another few open issues and common user confusions too. Then we you could have structures like:
And if you were in the "cmd2" directory and ran go install, it would walk up, file "gopath", and prepend that to your $GOPATH environment, which will likely be empty for new users in a GOPATH-less world. "go get" and everything would work. "go install" would need a bin directory to write to. $GOBIN exists and would be used first. If unset, it could be write to $GOPATH/bin. (yes, there's no gopatch/src in this proposal. Maybe it could exist, but it seems unnecessarily deep) Or we put the default $GOBIN elsewhere. Anyway, the point is that I also don't like $GOPATH. It's just a lot of design & implementation work, and nobody's on it, at least yet. |
Or, a revised version of the above proposal: Instead of the magic directory being Then the implicit $GOPATH/bin would be So:
And there would never be a |
@bradfitz I think using
This can live in tandem with existing $GOPATH. In Java / C#, I also often expect a local "bin" and "obj" or similar directory, so I wouldn't make #4719 a dependency, just when that gets resolved, the pkg dir would no longer be needed. The local "bin" would stay. A dependency of this would probably be a standard "go dep" tool to put the root path specifier. A small side note, govendor and godep write down the path in their manifest files today so services such as heroku can build the project with just the vcs repo. |
@bradfitz #14566 is not a duplicate of this... it's the case where we (may) have a GOPATH but want to build something from outside of it. This issue won't solve it at all. To solve #14566, we need to be able to specify the package we are in (for instance with a "--local-package=foo/bar" flag) and have everything else work by default (including the vendor directory). |
It might not be an exact duplicate, but the issues are all closely related. Using this as the tracking issue is good enough. |
Ok so now this issue also includes solving the need to override the local package's "reference" when outside the GOPATH. From the top of my head, 2 proposals where made: the flag solution I just put and the "godoc" like comment solution (ie: |
I'm fully aware of the diamond problem, thanks for the oops right there :) Yes, but if you also read what I've wrote, it shouldn't be up to Should we also discuss about the complexity of resolving all dependencies in automatic way?
In my opinion, no. That's a can of "goodies" that it's best left unhandled by automated tools in a "smart" way. Again however, this shouldn't be a problem that We also have two problems here:
If the first thing happens, then you are lucky. But it's highly likely that a similar situation as the one you are describing, where a small change that technically doesn't effect the API but the behavior of the package. For this and the latter case where a user doesn't follow semver practices you really have a single solution: ask the user to solve the conflict issue. We could argue for the third case where people don't version their repos but then we can also say: just fetch the HEAD and let the users complain about the missing versioning.
It's a problem today for get as well, with the GOPATH only, not just the vendor folder. I'm sure there's someone that will soon point out even more issues, hypothetical or real, but again, I urge you, please take a couple of steps back and ask yourself:
I'm not saying effort shouldn't be put into trying to solve as many issues as possible and make the life of the users as good as possible. |
Coming from the ruby world and having dabbled with node, my personal practical experience as well as theoretical belief totally concurs that using a single version of a lib is the way to go. Go has the added benefit that an incompatible version has a greater chance of being detected statically at compile time compared to dynamic languages which have to rely on tests. If something arises from detecting an incompatible version whether through semver, static analysis, or tests, then it means some mess needs to be sorted out, and the node way is just trying to sweep it under the rug, only adding complexity to the table when (when!) you have to untangle object lifecycle through multiple versions of the same lib that may have subtly different expectations of data structures as well as behaviors. |
@rsc this is the issue we've talked about at GopherCon. I believe that the proposal to have a "virtual GOPATH" created based on the In my simplistic view, this could be done for Go 1.10 but I defer to your judgement if this could be approached in the proposed format, or otherwise, by then. Thank you. |
I think that it would be a good time to revisit this proposal that was put on hold 15 months ago (/cc @bradfitz @rsc). My experience hasn't changed much since I opened this proposal, and the default |
Unholding. |
What I'd suggest may have been already proposed. Anyway
This way, each project is self-contained and can be built right from sources, without managing dependencies and their locations manually |
This issue will be resolved should vgo or similar solution be adopted. The need for a GOPATH env var goes away when adding a go.mod file with the module root path. |
Different projects can have different versions for packages. I would strongly suggest to have dep ensure still use a project-specific cache: either |
Could the cache be keyed on the name and version of the package rather than just the name? |
Given that they're just files (and therefore could have been modified), I'd suggest keying on the hash of the package source instead of any surrogate key. |
Hey all, My experience covers work both inside a mono-repo and with individual libraries, with either fully vendored dependencies or with all the dependencies already inside the repository. The extra GOPATH structure has added little value while making it annoying to set up and manage clones of the repository under development. I’ve been experimenting on implementing some of the changes necessary to work without a GOPATH (in a repository with fully vendored dependencies) to see what it might entail. As far as I can tell, this change is comparably small and localised, although I didn’t implement a complete solution. A possible way to allow users to use the build tools without a GOPATH might be to walk up the filesystem from the starting directory until a source file with a specific directive (e.g. I think this allows new GOPATH-less-capable repositories to be fully compatible with older toolchain versions (the prefix directive can be ignored if it is located in a directory below a GOPATH root). Also, because the prefix scan occurs just once and picks the first prefix it finds, ambiguity from having multiple such prefixes is avoided and minimal build overhead is added. Because the source tree behaves as if placed inside a virtual GOPATH root, most of the build behaviour continues to work unchanged, and import statements do not need any adjustment. Disregarding the particular details though, it would be great to see some movement on this issue. |
@devenv and any others: @rsc is currently working on a proposal that will not only take care of this issue (completly remove the need for GOPATH), but also take care of making imports version aware. His papers on the subject: https://research.swtch.com/vgo Right now his proposal issue is empty and used as a placeholder for drafting the proposal text CL. |
We're certainly moving toward "modify the Go toolchain to work without GOPATH", so accepting that idea, although not the details in the top post above. It will take a few releases to get there. The steps are
We're not ready to do 2 yet. |
Duplicate of #4719. |
Over the years, when helping people approaching existing Go projects (colleagues, friends, etc.) the number one problem is of course that they don't know about
GOPATH
, they don't have one configured, and they expect to be able to clone an existing project wherever they want on the disk, and be able to build it. I think the problem statement is clear and the problem is well known.With the introduction and adoption of the vendoring folder, most Go applications do not even require
go get
to run, after the initial clone: all the source code required to compile them is already available in the source tree; it's just that the Go tool doesn't know where to look ifGOPATH
is not defined.Instead of suggesting a default
GOPATH
(which does not solve the fact that people will need to find out about it and use it somehow), I suggest that we change the Go toolchain in multiple steps (each one can be independently released as an experiment):GOPATH
is not set, the Go tool will use any existing./vendor
directory as it was part of theGOPATH
. (I think of this as defaultingGOPATH/src
to./vendor
). At leastgo build
andgo run
are guaranteed to work. Anything else, likego install
andgo get
, would fail with an error pointing to theGOPATH
documentation.GOPATH
is not set, the Go toolchain would be updated to use$HOME/.gopkg
(or similar) aspkg
directory. This would allow other commands to work (e.g.:go build -i
orgo install
).GOPATH
is not set,go get
(or the new package manager, if/when it gets released) would be modified to download packages directly into./vendor
As shown in Step 2, I think this proposal would also interact well with the existing proposal/discussion of dropping
pkg
in favour of a hidden cache directory, as that would move things further into the direction of not needingGOPATH
anymore for a whole class of development; in fact, this functionality could be prototyped in this specific scenario of "GOPATH
not defined", where it would make sense to do it without facing the bigger discussion of deprecatingpkg
for a normalGOPATH
scenario.As shown in Step 3, I also think that this might interact well with the new package manager. I saw many people requested that the new package manager ought to be able to download dependencies directly into the vendor folder (like
govendor
andglide
can do); if this functionality lands in the new package manager, it would be a perfect default for the "GOPATH
not defined" scenario described here. Alternatively, it might make sense to discuss modifyinggo get
to have this behaviour.I think this proposal is incremental, backward-compatible, doesn't affect existing users that successfully use
GOPATH
, and allow beginners to approach existing Go codebases without stumbling too soon intoGOPATH
.The text was updated successfully, but these errors were encountered: