-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: keep GOPATH mode #37755
Comments
although I do disagree, the editing repos locally is really nice |
It should be helpful to identify more precisely and write down what types of workflows are currently easier to achieve in GOPATH mode than in module mode. That would make it possible to investigate if the module mode can be improved so that those workflows do not have more overhead in module mode compared to GOPATH mode. |
I don't think we should maintain I'd much prefer we improve modules so that this workflow is better supported. Editing and releasing multiple modules has been a problem, and we should figure out a solution to. As @dmitshur said, it would be helpful to explain your workflow and exactly why it doesn't work well with modules. Please consider adding an experience report. |
I think the issues are well documented in #26640 -- here's my summary:
So, while this is not the absolute worst situation in the world, it is a lot of seemingly unnecessary overhead, given the pure transparent simplicity of GOPATH. With GOPATH, all core developers could just use that mode, and either work in a branch and do nothing at all at commits, or require users to check out tagged releases to get reliable behavior (or use GOPATH when using the latest HEAD), or have a simple Makefile target that updates go.mod to latest revision. In short: there are different modes of working, one where you're relying on stable existing package API's and want reliability and stability, and another where everything is changing and the "live source" model makes more sense, so supporting both modes separately may make more sense than trying to find one solution that works for both, when each has very different fundamental requirements. |
I would like to chime in with a real life example: ContextI develop a family of machine learning and deep learning libraries - gorgonia. Roughly speaking the libraries function as such:
These libraries each do similar but different things. For example, a Since they do similar but different things, it would be useful to have similar APIs in the packages. The versions are kept in sync, so all the packages have similar APIs at any given version (well, that's the goal). The dependencies look like this:
Despite The ProblemCurrently with Go modules, I have found it quite difficult to simultaneously work on all three libraries at the same time. My solution thus far has been to just use Now I think Go modules are one of the more brilliant things about Go. However, it isn't very clear how to simultaneously work on newer versions of the libraries. Other methods I have tried: Work using Go modules. Say I am working on A and B at the same time, and B depends on A. I first add the APIs to A, publish, then add the latest version as a dependency of B. This approach works but generates a lot of superfluous version numbers. This is especially true when working to discover the best most userfriendly APIs. Often it's the API of B that determines the API of A, despite the inversion of library dependencies. ConclusionIt's difficult to work simultaneously on multiple co-dependent library (co-dependent in the abstract sense - the actual dependencies are unidirectional). GOPATH helps with that. I view GOPATH as the "working bench" before publishing |
It seems to me that the local go.mod idea described in #26640 would address this. |
This proposal does not seem actionable: it is proposing that we not-do something (removing support for GOPATH) which we have not yet proposed to do anyway (#4719 notwithstanding). Moreover, I think the emphasis on #26640 is telling: note that that issue is still open. It seems premature to prescribe a course of action based on this assumption that that issue, or its underlying use-case, will not be addressed. (But #26640 itself seems like a bit of a red herring: the real issue to focus on here is the use-case, not the mechanism. #26640 describes one possible mechanism, but I believe the underlying use-case is #27542, and it may turn out that we can better address it by some other mechanism.) |
Wouldn't it be good to have a clear plan going forward? If there is a clear plan to retain GOPATH, then it seems like that would change the way that these other issues are addressed? According to the oft-cited principle of feature-orthogonality, wouldn't it make sense to not try to shoe-horn GOPATH into go.mod, as in #27542 and #26640, and instead focus on doing whatever might be necessary to make the two modes of operation (GOPATH and go.mod) more cleanly supported and well-documented etc (e.g., the GO111MODULE env variable is likely a suboptimal way of switching between modes -- perhaps a command-line switch instead or at least in addition? And at least a better name for the env variable?) From this perspective, the discussion in #27542 seems to support this approach, as it was largely focused on essentially just replicating GOPATH under go.mod. Again, the proposal here is to just embrace these two modes as serving largely different use-cases, and adopt the principle of orthogonality, etc. Also, again repeating myself, GOPATH is really really simple, and that is a major advantage over trying to replicate its functionality in some more complicated way on top of go.mod. Let go.mod do what it does best, and GOPATH do what it does best, and forget about all the replace directives etc. |
I think this would be a big mistake. Go is often criticised for having more than one way to do certain things (such as declaring variables), and I take that point. For beginners, it's much less confusing if there's one straightforward, standard, official way to do X. Once upon a time, the standard way was GOPATH. Now it's modules. Don't look back, look forward. If a few people decide to stop using Go because they loved GOPATH so much, I personally can live with that. |
Users have expressed directly to the Go team, more than once[1][2], that they are unhappy with GOPATH. Go modules were put in place, in part, to solve that 'unhappiness'. reference: |
Oh! An astounding one percent of users were unhappy. I would like to see how many users with over a year of Go experience who used Go at work complained about GOPATH. If there was more than a single such person, ofc. Many expressed a need for better dependency management tools. But not one I know had wished for GOPATH to be fierce slayed. |
GOPATH cannot provide proper versioning. GOPATH was nice and seemed simple. If, as I often say, Having two incompatible ways to do something - both GOPATH GOPATH is holding back the ecosystem and the toolchain. |
And still it is used (is the only straightforward way) to experiment with, or debug interconnected modules. Please come with a solution to the #26640 issue first, then GOPATH may retire. |
@rsc says:
So I second @ohir: to me the right sequence of events is:
I recently migrated my projects to modules, but, surprisingly, have to keep using GOPATH for development primarily due to workflow issues when one needs to work on several modules at the same time. |
@rsc:
How can you possibly argue with that! Except, if you transport yourself back to your first experiences in programming, before it got weighed down with all those other people and all that time, and can remember the pure joy of just doing something direct and simple, like writing BASIC on the console of a PC (for me it was a TRS-80 Color Computer, where I tried and failed to write my first AI program in high school, but settled for lots of fun graphics instead :) I'm sure nostalgia has no standing in the pragmatics of the matter, but anyway if it is possible to make it as easy as possible for people who aren't software engineers to also use Go for the pure joy of it, that would seem to be a good thing. And there is nothing about modules necessarily preventing that -- just need to figure out these issues.. And speaking of which, I'm having a hard time tracking the current status of things -- it seems like #34506 was implemented but it doesn't solve the inter-dependent issues because it only applies to one module? And if you set the GOFLAGS env it applies to all modules? Is someone in the know going to update #26640 with a summary and proposal or something? Seems like it is in some kind of limbo state? |
Based on the discussion above, this proposal seems like a likely decline. |
GOPATH is incredibly useful for everyone who doesn't like The git tools for working with different library versions with submodules work great and it makes it easy to allow most deps that are stable to be constantly built from their |
People do use source control systems other than Git with Go. |
I hope that you'll take a quick moment to reconsider your comment. I feel you might have just pre-made up your mind, and so I hope you'll consider this: Of course people use other systems than git, and you can use a submodule equivalent in those systems too! Just as a single golang project doesn't require every dependency to be in git, doesn't mean this can't continue working the way it was. Firstly: most people are on git anyways I realize most Google people don't care about this because they have their own internal tools that do all of this for them, but hopefully you'll not break GOPATH for everyone that has been using it since the very beginning. Thanks! |
This addresses an older #37755 (comment) but since solutions for some of the issues raised therein are older (by an order of magnitude) than that, I felt this may still be acutely relevant to at least some.
That dependency graph (
Here is yet another point where the design brilliancy of Go modules shine: since
But of course you have to publish the changed dependencies before you can publish whatever depends on the changes! That just is the reality of software development, regardless of languages, libraries or dependency management systems; that's the order in which you also have to publish the changes when using This is what I felt I had to vent over complaints about Git workflow with Go modules and ISTM this also pretty much addresses the rest of the points in #37755 (comment). Concerning Go modules versus |
For what it's worth, on a day-to-day basis I only use the open source Go tools. I go months at a time without using any of Google's internal build tools or source control, and the same is true for most of us working directly on the open-source project. So the assertion that the decision to retire GOPATH is overfitting to some Google-internal development system is untrue.
As @antichris linked above, I hope the rationale in #37755 (comment) is pretty clear that GOPATH does not work for many cases. There is also a very high cost to keeping it, because we cannot make it work as well as modules. It complicates every new thing we want to do in the go command, and it greatly increases the support burden. But most important of all it fragments the ecosystem. As I also noted in that comment, the major thing we need to fix is to provide some way to work on a collection of modules simultaneously during development, even though they will get released separately. We have some ideas that not quite well-formed enough to state clearly, but we intend to do something for Go 1.17 to address this. |
@rsc > There is also a very high cost to keeping it, because we cannot make it work as well as modules. But there is a cost that removing it causes troubles to old code using GOPATH that you didn't count. I don't think your justification make sense in all cases. Therefore, GOPATH is better to be maintained to ensure backward compatibility. |
@ssxcxS45XT No. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I understand your frustration. I've had my own fair share of dealing with messy projects over my decades of development. But it is based of this experience that I can also tell you that almost everyone who started out with a big sloppy heap of globally shared dependencies have taken steps to migrate to (or at least, implement) some form of isolated, modular dependency management. When the initiative doesn't come from the language designers and maintainers, it often is the community that takes action to improve the situation. To name a few, Composer, Bower, Bundler, Maven, NPM, NuGet and PIP — none were there when the language first came out, none of them were originally developed and released by the official language maintainers, and a select few of them have been embraced and accepted as the official dependency management tool by the respective language project (if there even is one); it is only Rust with Cargo, who were built from the ground up with each other in mind, AFAIK. But all these tools are indispensable in their respective roles, and engineers nowadays would not imagine achieving their goals without them. One could even argue that Docker is a tool that serves the same purpose — bundling a piece of software with its dependencies in a reliably reproducible unit of deployment.
Yes! You're getting it! The Go's plan here is precisely to ditch the arbitrary pile of shitty features that is In my very personal and highly subjective opinion, world (at least, the computing one) would be a better place if everyone adopted Go modules' approach to the software dependency management problem: installing an application you choose the version you want; its dependencies, having been picked and tested as a whole by the developers, do not affect the dependencies of any other application, agree among themselves upon the lowest common acceptable versions, and are not copied to a huge number of instances between various applications. I remember back in the day when I was still working with NPM projects, we had tens of gigabytes of the same dependencies copied over and over again, each project having a maximum of few tens of megabytes of original content, but gigabytes of copies upon copies (at slightly different versions) of dependencies. And the Composer projects that could not take new dependencies (i.e., you can't add another library or tool) simply because they were stuck in a needle-point-narrow compatibility spot of version constraints; one could spend days trying to debug and patch through the dependency hell. Truly awful shit, I couldn't be more happy I'm done with it. So, yeah, rest in peace |
@antichris take it easy there John Oliver! :) I do agree that Go modules are really great (modulo the multi-module issue), but like all things it took a bit of experience to really appreciate how well they work, and once you get comfortable with the new model, it is hard to see going back. That said, I still spend 100% of my time developing in GOPATH mode due to the multi-module issue (and some kind of weird slowdown associated with #29427 that I need to investigate further). Looking forward to the 1.17 plan! |
GOPATH is going to be removed in Go1.17 (see e.g. golang/go#37755 (comment)). -> Prevent programs suddenly become installed into $HOME/go/bin instead of gowork/bin, and mod cache to become something like $HOME/go/... instead of being kept under gowork/ No change in behaviour for Go ≤ 1.16
Add support for using Go modules to golang/gowork infrastructure: - Users can now request to install a module via gowork:install as. e.g. in the following example: [gowork] install = lab.nexedi.com/kirr/neo/go/...@v0.0.0-20210103165133-f3effa6c535f golang.org/x/tools/gopls@v0.4.3 ${helloweb:location}/go:./... The first two request to install programs from an external module at particular revision/version. The latter requests to install programs from locally cloned/checked-out module source. The documentation now talks only about programs, because "package installation" became unnecessary long time ago as Go toolchain uses right packages and recompiles things as needed automatically since introduction of the Go build cache in go 1.10. - The change comes accompanied by corresponding helloweb change that reworks it to a) become a module itself, and b) to use other modules - that are not explicitly cloned by buildout - so that we can be sure that module way of fetching/building things actually works. https://lab.nexedi.com/kirr/helloweb/commit/a7c788ae71 - Non-module way - e.g. build via GOPATH - is still supported (because e.g. software/gitlab still uses it), but not explicitly documented and scheduled to be deprecated and removed. The reason for this is that upstream Go is going to remove support for GOPATH and leave only module-based approach in Go1.17 golang/go#37755 (comment)
Add support for using Go modules to golang/gowork infrastructure: - Users can now request to install a module via gowork:install as. e.g. in the following example: [gowork] install = lab.nexedi.com/kirr/neo/go/...@v0.0.0-20210103165133-f3effa6c535f golang.org/x/tools/gopls@v0.4.3 ${helloweb:location}/go:./... The first two request to install programs from an external module at particular revision/version. The latter requests to install programs from locally cloned/checked-out module source. The documentation now talks only about programs, because "package installation" became unnecessary long time ago as Go toolchain uses right packages and recompiles things as needed automatically since introduction of the Go build cache in go 1.10. - The change comes accompanied by corresponding helloweb change that reworks it to a) become a module itself, and b) to use other modules - that are not explicitly cloned by buildout - so that we can be sure that module way of fetching/building things actually works. https://lab.nexedi.com/kirr/helloweb/commit/a7c788ae71 - Non-module way - e.g. build via GOPATH - is still supported (because e.g. software/gitlab still uses it), but not explicitly documented and scheduled to be deprecated and removed. The reason for this is that upstream Go is going to remove support for GOPATH and leave only module-based approach in Go1.17 golang/go#37755 (comment) /cc @jerome, @luke, @tomo, @alain.takoudjou /reviewed-on https://lab.nexedi.com/nexedi/slapos/merge_requests/924
GOPATH is going to go away in Go 1.17 and most of in-tree SlapOS things are already built using modules - including upcoming wendelin.core 2 that also builds/uses NEO/go. This way maintaining GOPATH-based approach becomes just unneccesary burden (modulo development, where it is still needed sometime unfortunately golang/go#37755 (comment))
Add support for using Go modules to golang/gowork infrastructure: - Users can now request to install a module via gowork:install as. e.g. in the following example: [gowork] install = lab.nexedi.com/kirr/neo/go/...@v0.0.0-20210103165133-f3effa6c535f golang.org/x/tools/gopls@v0.4.3 ${helloweb:location}/go:./... The first two request to install programs from an external module at particular revision/version. The latter requests to install programs from locally cloned/checked-out module source. The documentation now talks only about programs, because "package installation" became unnecessary long time ago as Go toolchain uses right packages and recompiles things as needed automatically since introduction of the Go build cache in go 1.10. - The change comes accompanied by corresponding helloweb change that reworks it to a) become a module itself, and b) to use other modules - that are not explicitly cloned by buildout - so that we can be sure that module way of fetching/building things actually works. https://lab.nexedi.com/kirr/helloweb/commit/a7c788ae71 - Non-module way - e.g. build via GOPATH - is still supported (because e.g. software/gitlab still uses it), but not explicitly documented and scheduled to be deprecated and removed. The reason for this is that upstream Go is going to remove support for GOPATH and leave only module-based approach in Go1.17 golang/go#37755 (comment)
I felt a lot of friction comming from other languages with package managers. finding this GOPATH thing that we had to set to be able to run the Go hello world was not a good first time user experience. However with time I learned how using forks as version locks and
A little copying is better than a little dependency.
Don't panic. Please consider not breaking something that its not broken for a lot of people, I think that theres a lot of value in that. Thanks for all the efforts, looking forward to 1.17! |
I have to say, a single directory
|
This proposal is simply to retain the existing GOPATH functionality, along with the go.mod modules.
The rationale is that GOPATH provides an ideal mode of operation for developing across multiple different repositories at the same time. It is otherwise cumbersome to do so with go.mod, requiring e.g., temporary insertion and removal of replace directives (see discussion in #26640).
A major design priority for Go is simplicity, and GOPATH is simple. It provides a great way for new users to explore lots of different code packages easily, browse, modify, experiment, etc.
There are many different types of Go users, but it would be great to retain support for the "hobbyist" / non-corporate hacker who just wants to do things simply and doesn't care about living on the bleeding edge.
It should not be so hard for the two modes to coexist, as the tooling etc is currently supporting both, and I personally find it most productive to develop in GOPATH mode and then have some Makefile targets that ensure go.mod still works for those who want to use that. And all official releases are done in go.mod.
Thus, it may actually be optimal to have both modes available, instead of trying to complicate go.mod so that it does what GOPATH already does so well.
The text was updated successfully, but these errors were encountered: