-
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: introduce 'module GOPATH' to allow transition from GOPATH to modules #44649
Comments
This is clever and would have helped me a number of times. |
See #44660 |
Hi Bryan, I like this idea, and I very much like the general concept of a gentler on-ramp to modules and import paths and so on. One thing to consider is a graduation mechamism. Ideally, cmd/go would rewrite the import paths and module path in a consistent manner. In other words, something like start via It would be nice if cmd/go could cross the import path editing rubicon (which might also justify a cmd/go version of #32014), but if not, some gopher from the broader community would almost certainly create some flavor of a go-mod-graduate or similar. If some version of what you outlined was supported, I would likely recommend it as a starting point to some of my colleagues who have written plenty of Go, but who still fumble around when starting a module from scratch. An automated graduation path in turn would help them transition if needed to a working, consistent full-blown module, which is then much easier to expand upon. |
@thepudds, I think we already have a graduation mechanism: namely, carving out “nested” modules, where in this case a “nested” module is any module with a non-empty import prefix. That is: at any point, you can carve out any subpackage into a module by... making it its own module, and adding a |
I used to do the same kind of GOPATH tinkering and I've got used to |
This almost seems like a re-introduction of the previous vendor behaviour. |
@icholy, the crucial difference between this and (In module mode, there is only one |
Why not just omit the module name?
|
Maybe! But is that too difficult to distinguish from an accidental typo? (I'm honestly not sure.) |
Actually, that won't work. Older versions of Go will choke before getting to the
edit: but I guess that wouldn't matter because it can't be required. |
maybe? |
That doesn't particularly matter, because older versions of Go won't know how to interpret a prefixless user module anyway. 😅 |
warning, heavy speculation: If this gets accepted/implemented, prefix-less mode will become the preferred choice for non-library modules. Once/if that becomes the case, people will also want to write prefix-less library code. This will become a point of contention. |
If we do this I think it should probably be the suggested way to migrate from GOPATH to modules incrementally, at which point One detail I don't quite understand is what to do about imports of code from GOPATH that is itself covered by other go.mod files. For example if we have
then it seems clear that the import should resolve to GOPATH/src/example.com/b/b.go. |
This comment has been minimized.
This comment has been minimized.
@ohir, this proposal is not intended to address simultaneous editing of multiple modules. That will need to be addressed separately. This proposal is specifically intended to address module migration for existing projects (large or small) that rely on packages that, for whatever reason, already cannot be fetched using That may be because they are hobby programs, or programs that generate additional code using |
Ah, indeed. I humbly apologize for my off-topic comment above. |
Hmm, good question. Normally we would prune out the nested module, but if we're applying the legacy I'm tempted to suggest that we wire in nested modules using |
I think I agree. If GOPATH/src/go.mod says 'module GOPATH' and GOPATH/src/example.com/b/go.mod says 'module example.com/b' and I cd into 'example.com/b' and run a go command, then I assume it uses example.com/b/go.mod and not GOPATH/src/go.mod? That is, the command runs in the example.com/b module and not the GOPATH module? |
Yes, I think that's correct. If you want to run a command in the Changes to the source code found in of any of those nested modules would be reflected in the |
This proposal has been added to the active column of the proposals project |
@robpike But I think only if the content in syntax & semantics as proposed here goes into some venue other than @bcmills I was not sure I'm on the same page until I see #27542 shortly earlier, I understand the situation exactly as you stated it there. I had been and still am missing Go ever since switched to Haskell a couple of years ago, Go tooling is always the most pragmatic one to my experience, (but I need more powerful abstraction tools there plus the M:N scheduler of GHC RTS as well as Go offers). But w.r.t. the "project" thing, I realize that both Haskell build tools, namely Cabal and Stack, got it right beyond modules and packages. Situation wrt building tools are even messier and more confusing to outsiders in the Haskell ecosystem, but this stackoverflow answer may explain why "project" is important (as well as to Gophers): https://stackoverflow.com/a/49776281/6394508
Update: I would suggest you replace "package" as heard from a Haskeller, with "import-root" in your Gopher's mind for clearer understanding. I realize that Java might have started use "package" this way even before Go, that's apparently not wrong. But when you talk about "package" and "module" to Haskellers, or Python guys, the terminology can be a source of confusion. |
@meling I have nothing of objection except for the nesting of Go modules, I'd think that's a bad idea if feasible. What's the identity of a sub-module nested within a parent-module, if it can be separately published as well as part of its parent module? Or if it can only get published with its parent-module, you'd allow a separate version from its parent-module's version be specified as a dependency? If yes, it can be confusing for a dependent app to require multiple different versions of a parent module at the same time, for different parts of it; if no, then this sub-module thing seems to have no purpose of existence. |
This — working with many interdependent modules — is specifically addressed by the #44347 proposal. This proposal (treat GOPATH tree as a modules tree) is in my opinion better regarded as a migration tool that can help to move big internal code trees to the modules ecosystem. Both proposals are complementary, IMO. |
agree on this point, does #44347 expects .mod files? would be nice to have a way of dealing with this error that is not turning off modules or adding a .mod file:
|
It does recognize go.mod files and uses them for resolving and using dependencies that are not present under GOTINKER tree. It need not to mandate go.mod files to be present though. Note: Please keep 44347 related discussion there, not here. |
I agree. This proposal ( To reiterate: the problem of editing interdependent modules is important, and we (particularly @matloob) are actively thinking about ways to address it, but I think that problem is off-topic for this particular proposal, which explicitly does not address it. #27542 is the right place for brainstorming about that more general problem. |
Like Russ, I think the value of this proposal is questionable when considered just a migration path. However, this proposal's use cases and multi-module use cases seem similar enough that I don't understand why you don't want this proposal to cover the multi-module cases as well. Or, start with the multi-module case and let it cover "GOPATH-mode" described in this issue as well. I'm asking because a draft proposal for multi-modules involves introducing yet another configuration file with its own semantics - which is much less appealing to me than extending go.mod to deal with multiple simultaneous modules. I don't care much for migrating prefix-less import paths, but I care a lot for the simplicity of this proposal. |
Out of curious, why that draft proposal points to a non-existing https://golang.org/issue/NNNNN issue for purpose of discussion? I actually want to vote for that proposal, since an independent layer for dependency resolution is not unusual wrt software engineering, and I would suggest Haskell ecosystem/tooling has a success showcase with this regards. |
@eliasnaur, I have read Michael's multi-module draft and I believe that this proposal and that draft are complementary, not alternatives to each other. This proposal allows for a single module with a prefixless import path and a single set of dependency requirements, but allows that module to span multiple disjoint import paths. In contrast, that draft allows for combining and manipulating the requirement sets of multiple otherwise-independent modules, but does not allow any of those modules to individually span disjoint import paths. |
@eliasnaur What would extending go.mod to supporting multiple simultaneous modules would look like? @complyue I'm planning to make a formal proposal later this week, but I don't think that the draft is completely ready to start that process yet. If you have feedback though, I'd definitely appreciate it. Feel free to send me an email or comment on the golang-tools thread! |
This comment has been minimized.
This comment has been minimized.
@matloob good question, and I don't have a complete answer. I'll describe what I had hoped this proposal could do for me. I have two modules I regularly work on, Now, inspired by this proposal, I propose something like be made possible:
The Comparing the go.work proposal, by placing modules in directories matching their names, the |
@eliasnaur I think we need to add a new type of file to support the multiple module workflow. The scope of a go.mod file is already defined to carve out other modules that exist inside it, which would make it difficult to add support for the file to apply to other modules contained within that module's directory tree. And I think changing those semantics for a About your proposed workflow: I agree that there's an extra clunkiness to having to specify each module in the file, but I think there could be a solution to that in the framework of But I'm already getting off topic on this proposal... |
I'm not sure I understand your point about scope. If I
|
I spoke to @bcmills, @jayconrod, and @matloob about this yesterday. I think this would have been a great idea four years ago, but today it probably carries too much complexity for too little benefit. It sounds like we should probably just leave things as is and not adopt this proposal. Will wait a week to see if anyone wants to make the argument to the contrary. Note also the design draft (as yet not formally proposed) at http://golang.org/design/draft-workspace. |
does this mean keep GOPATH and GO111MODULE until we have a solution that deals with
We should consider that not every team and project needs or wants a package manager. We should have a way to opt out, actually we do already, just not removing it would suffice.
I don't understand why wanting to keep compatibility with a build system that works for many people is considered an |
@benitogf I think that your comment above belongs mostly to #44347, not here.
"Attitude" because GOPATH based builds are deprecated except for remnants in the form of private/company internal code. This (#44649) proposal tries to keep it buildable as-is. Note, that most of public (open source) code is now attuned to the Go modules versioning. It means also that authors now need not to adher to the "HEAD/tip is the release" principle — most still do, but the mental barrier against pushing experimental code at the tip is wanishing.
Thinking about this is in progress, as seen in both cited proposals. There is also @matloob's #45713 "Add a workspace mode" proposal — bringing to us yet another way to write and build Go software. |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
In versions of Go before modules, users were able to set up a single
GOPATH
containing a group of interdependent packages. With the advent of modules, a single module may contain multiple interdependent packages. However, all of those packages must share the same import-path prefix, which is the module path declared in the main module'sgo.mod
file.For some users — especially hobbyists who did not publish their code for external use — the process of migrating from this “global” namespace to the “local” namespaces of modules can be burdensome. (See, for example, the various discussions in #37755 and #44347.)
When we started using modules to manage the vendored dependencies of the Go standard library itself (#30241), we created a special
std
module which, unlike all other modules so far, does not add an import-path prefix to the packages it contains.It recently occurred to me that we could use this same approach to allow “tinkering” users to more easily convert their
GOPATH
workspace to work in module mode.For such a module:
The
go.mod
file would explicitly indicate that the user wants a module with no import-path prefix, perhaps by declaring a distinguished module path (module GOPATH
ormodule src
?) or using a special directive (noprefix
?).Within an unprefixed module, the usual module-mode commands, including
go mod tidy
andgo get
, would be supported.go get
would add module dependencies as in module mode, not clone repos into the local module as in GOPATH mode.No other module may itself
require
an unprefixed module. (This is to preserve the invariant that a user can identify which modules may contain a given package by comparing the package path to the module path.)As in an ordinary module, collisions between packages defined in the unprefixed module and packages defined in the module dependencies of that module would not be allowed.
CC @jayconrod @matloob
The text was updated successfully, but these errors were encountered: