-
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
cmd/go: rethink "missing go.mod" mode #32027
Comments
Some ideas (separated for emoji-response tracking):
|
The downside of that approach is that it would be really easy for users to unintentionally get stuck on some really old version of a dependency and never realize that they need to upgrade it. (That's one of the more annoying failure modes of |
That would at least prompt the user to run |
An important use case for no go.mod file are tools that do not use any imported dependencies. For certain software, such as, say, a Go module proxy, or a simple command line tool, the programmers might want to avoid a chicken-and-egg bootstrap problem and therefore depend only on the Go standard library. Whatever the solution, I'd like this use case to be taken into consideration. |
@beoran, maintaining a I think the bug-testing and legacy-GOPATH use cases are more compelling. |
Looking at cmd/go/testdata/script/mod_outside.txt, the only "slow success" cases (where there's no go.mod so every execution has to re-resolve unknown imports) are things like 'go run x.go' (or go build, go vet etc) where x.go contains an import of a package from outside the standard library. If we make that case fail with a message about not having a go.mod, then I think we can consider this issue fixed as far as blocking setting GO111MODULE=on by default. |
Change https://golang.org/cl/198778 mentions this issue: |
I wrote this comment on the CL:
@bcmills replied
Let me defend First, this CL is taking away a useful, albeit slow, feature without a replacement. I don't consider the usual workaround "use go get and run the installed command" a good enough replacement for Second, this issue seems to be about running local Go packages and standalone programs. Quoting Russ:
I can live with not allowing
Ironically, both Note that even though I personally don't care much about Finally, is In short, I think submitting CL 198778 as is would be a mistake and I would be quite disappointed to see a useful feature go away for efficiency reasons. |
I ran the following experiment:
The first run completed in just under 5 seconds, the second in less than a second. For comparison, I ran
That is, a difference of ~200ms between inside and outside a module. |
That's an interesting input for #30515 / #34506. In particular, it suggests that we may want to allow Even then, I think that only |
To be clear, we're not planning to remove this for efficiency reasons: we're planning to remove this because we don't feel that it's a good user experience. When GOPATH is eventually deprecated and the default value of
GOPROXY certainly speeds things up, but asking for the latest version of a module can still be quite slow. If it's a module that is requested infrequently, the "latest" version may not be cached, and the proxy may need to fetch the repository again. Additionally, if any of the imported packages don't have go.mod files, we have to resolve the "latest" versions of their dependencies (and so on). Even in the fast case, you're going out to the network, which will be slower than local builds with a warm or mostly warm cache.
I read through #33518, but I'm not directly familiar with Gio, and I'm not really sure what the workflow is. Why is Also from reading the intro text at https://git.sr.ht/~eliasnaur/gio, it sounds like this tool builds and packages programs. Won't most users always be running it in their own modules? Also, shouldn't a fixed, predictable version of gio be used instead of the latest? |
Let me point out that it's not always slow. With a warm cache, my experiment above measures the difference in the hundreds of milliseconds. Furthermore, the output "go: finding blah go: downloading blah go: extracting blah" is a clear hint to why a cold
Ok, but for the second and subsequent runs,
As more and more people switch to modules, this problem diminishes. In particular when GO111MODULE=on becomes the default, which to many indicates that Go modules are "ready for general use".
I agree.
Most of the time, sure. But the critical time is when a newcomer evaluates Gio. I'd like for their experience to be as painfree as possible and being able to run a Gio program with a simple When a Gio user finally decides to use Gio, publishes their Gio program to some Git repository, they in turn can tell their users to evaluate it with just
I imagine most projects would like the simplest possible "get started" steps.
Sure, and that's why I suggest
outside a module. Responding to both @bcmills'
and @jayconrod's
Great, let's implement the replacement before killing off P.S. In case you think I'm making too big a deal out of |
It didn't occur to me before, but CL 198778 also breaks the gogio tool outside a module:
The |
Yeah,
But it would be pretty bad if, say, you ran |
That's assuming that the proxy has the module at all. For untagged, non-public modules, that query may involve fetching the head of the default branch of the repo and checking its |
If you're ok with Quick start instructions for Gio programs will change to
and to
for building an Android APK from a Gio program. |
This experiment only measures the fast case: the proxy already has the latest version of a project that has a go.mod file, and that version is cached locally. We're most concerned about the slow path where the proxy hasn't cached
I definitely sympathize with this, but I think it's important for the "first time setup" instructions to be close to the "everyday best practice". Running a build tool at the latest version makes me nervous: I'd be scared to put that in a build script or CI. As a user, I want to be able to list versions of my dependencies (both libraries and tools), and from that, I want reproducible output. So I'm not convinced that running Running these commands within a module seems fine of course, since the version will be recorded and the result will be reproducible. We know there are a number of issues around managing tool dependencies (#25922), and we're exploring some ways to fix that (#34506).
I'm happy to hold CL 198778 back for discussion for a little while, but we'd like to get it in for this release, and it should go in before the freeze. #30515 seems viable if it's accompanied by a better cache eviction policy, but it probably won't go into 1.14. I don't know what can be done to fix PATH though. It's admittedly confusing for new developers, but we do expect new developers to set that up when they install Go. I'd be surprised if we have a solution for that in 1.14, other than improved documentation. |
once #23439 is fixed you can instead express the quickstart instructions as:
or right now you could do
I guess we could also warn you if go get is going to write a binary to a place that is not on your PATH, but I think that would probably cause more confusion than it saved. |
go commands outside modules could be restricted to only work with projects with go.mod files. But if you insist that even the first invocation of
The difference between not encourage and flat out disabling functionality is significant. And again, please see my proposal above that won't use an arbitrary latest version, but rather the version in your modcache.
And #30515 is about
Which seems to contradict CL 198778 that disables anything else than Let's say #34506 brings back the functionality of
If you expect a certain PATH, why isn't the Go installer doing it? And why expect developers to set up PATH when you added That is very frustrating. You're removing functionality in Go 1.14 while leaving the (potential) replacements for Go 1.15 or perhaps later. |
By all means feel free to go ahead with CL 198778. I also found the cache argument compelling, and I found a workaround that works on Windows:
The first line feels like busywork, in particular the unused module name, but Bryan's argument does make sense: create somewhere for the |
When in module mode outside of any module, 'go build' and most other commands will now report an error instead of resolving a package path to a module. Previously, most commands would attempt to find the latest version of a module providing the package. This could be very slow if many packages needed to be resolved this way. Since there is no go.mod file where module requirements can be saved, it's a repeatedly slow and confusing experience. After this change, 'go build' and other commands may still be used outside of a module on packages in std and source files (.go arguments) that only import packages in std. Listing any other package on the command line or importing a package outside std will cause an error. 'go get' is exempted from the new behavior, since it's expected that 'go get' resolves paths to modules at new versions. Updates #32027 Change-Id: Ia9d3a3b4ad738ca5423472e17818d62b96a2c959 Reviewed-on: https://go-review.googlesource.com/c/go/+/198778 Run-TryBot: Jay Conrod <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
Change https://golang.org/cl/200297 mentions this issue: |
I think we missed a case: We should check test coverage for |
Change https://golang.org/cl/202697 mentions this issue: |
Change https://golang.org/cl/205065 mentions this issue: |
Updates golang#32027 Change-Id: Ifc9427f35188c3fd356917d8510f3e01866ebca8 Reviewed-on: https://go-review.googlesource.com/c/go/+/205065 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
Change https://golang.org/cl/216597 mentions this issue: |
Hopefully this won't affect many people, but it's a substantial change in behavior for a specific case, so it's probably worth mentioning. Updates #32027 Change-Id: I61cd50e93d0199e94b011cc90150e072b6bb10ca Reviewed-on: https://go-review.googlesource.com/c/go/+/216597 Run-TryBot: Jay Conrod <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
A few weeks ago, shortly after GO111MODULE=on became the default, I got to watch Rob using it. One problem he had was that when he worked in preexisting GOPATH directories, or just directories newly created for the purpose of testing one bug or another, there was no go.mod, so every go command reresolved "latest" for any imported dependencies. This made things much slower than they are intended to be (that is, much slower than they are when there is a go.mod).
I think we probably need to rethink what we do without any go.mod. There needs to be some place for the go command to write down its decisions from one command to the next. When people say "modules are slow" I wonder if this case is one of the things they mean.
/cc @bcmills @jayconrod @ianthehat
The text was updated successfully, but these errors were encountered: