-
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
cmd/go: go list has too many (more than zero) side effects #29452
Comments
Thanks for the report. At least some of the slowness you are observing may be imputable to outstanding cc @heschik |
@DisposaBoy (in a modules world) you need to move to use cc @matloob / @ianthehat - perhaps we should add some (temporary) documentation to |
cc @bcmills - should we also add an advisory to |
@myitcv I don't see how |
@DisposaBoy previously, multiple calls to If you continue to use
So the first step is moving away from If you are still seeing issues after moving to Issues that spring to mind include the aforementioned #29427, #28739. The latter is hopefully going to be addressed by an upcoming CL that works by caching directory/file operations where possible. |
@myitcv @DisposaBoy As much as I'd like to see everyone move to go/packages, I don't think doing so will help with these problems. The workings of modules, the build/list cache, etc., are complicated enough that we need go list as a black box to own the logic. Even if we had documentation about all this stuff (which would certainly be a good thing), it's possible that changes across versions of Go might break you, and having the go list logic reimplemented I think would just lead to bugs and incompatibilities. It doesn't seem likely to me that Go list will change to do less work, but I don't know enough about it and the workings of modules to say why. I'll leave that to @bcmills. Of course we'll work to get go/packages to use go list as efficiently as it can, but we'll be limited by the behavior of go list (which is in turn limited by the requirements of go modules). |
To the contrary, I expect that it will change to do substantially less work, especially when the |
See also #28692. |
At any rate, it is probably true that For example, if |
Why should |
Perhaps it shouldn't, but that still doesn't lead to “zero side effects”. For example, we would like If For example: suppose that you add an import of If In contrast, if |
So I could certainly buy the argument that |
@bcmills that makes sense. Is the fact that oauth2 does not have a go.mod relevant? If it did, wouldn't you still need to hit the network to find the latest minor/patch version since there isn't a specific version recorded in the local go.mod? Could there be a fast mode that just prints a warning to stderr and skips unresolved modules for tools that need to run as fast as possible and might not necessarily care that everything is worked out? |
Sort of. What matters is whether the requirements in the (transitive) |
|
Chiming in from #30090 - I found it counter-intuitive that
Unfortunately, entering my SSH password into the prompt was not sufficient, it still resulted in the secure password entry overlay being spammed repeatedly. Choosing to not unlock the keyring was likely was the cause of other problems (#30090). So the user experience wasn't great there. The circumstances under which it was doing network activity in #30090 came a bit of a surprise to me, because the code in question didn't have any dependencies which weren't already present in the module cache. It did eventually turn out that |
@balasanjay fine add go build to the list of commands that will pull dependencies down. It should however NEVER modify the version of dependencies listed in go.mod only the I cannot count the number of times running |
Caveat: I have no experience with these issues personally (my personal projects are small enough to not have CI, and my professional projects use a different build system entirely). That said, from reading rsc's articles, the impression I got is that In other words, it will not "upgrade" your dependencies willy nilly, but if your dependencies are insufficiently specified such that some change by someone else could change the meaning of your build, then it will change your I think if you'd rather never let it touch your |
@balasanjay the Currently Say Your project used libA(1.2.3) & libB(1.10.2) and libA also uses libB(1.10.2). Monday libB updated to version 2.0.0 from 1.10.2, you are all good since the module system will not auto update to a new major version. Tuesday libA updates to use version 2.0.0 of libB and bumps their version to 1.2.4 since this is just a performance improvement from their perspective. None of their public interfaces or APIs changes in any way. Well now your build is broken because the module system will auto update to libA(1.2.4) which will pull in libB(2.0.0) which is incompatible with your own use of libB. This scenario gets worse when teams do not understand they released a breaking change or are still releasing a v0.x.x library that is very widely used or do not use semver at all. Implicit modification of dependencies is never the right choice, it should always be an explicit decision on the developers part to update or modify their dependencies. |
There is no "auto update" to libA(1.2.4). What are you talking about? If your go.mod contains libA(1.2.3) then it will stay at that version. You have to manually update via On top of that, libB(2.0.0) must be able to run in parallel with libB(1.10.2). Most libraries have this property by default. The exceptions are libraries that have some sort of global state, like listening to a specific port. This is a known pitfall and there are solutions against it. Basically the library authors have to respect the Go module system rules, among which is that major versions have to be able to run at the same time. |
@xStrom if you start using another bit of code that requires at least 1.2.4 of course there will be an auto update. go.mod versions are not a lockfile, they are the minimal state the module engine will try to achieve. That's a try not a hard promise. |
like almost all the logger, config, web framework libraries in existence. |
@nim-nim if you update some dependency manually, then I think it requires some serious mental gymnastics to call this an auto update. When you do a manual update and your code stops working, then you can investigate and/or downgrade. Whether this issue is caused by the direct dependency you updated or some sub-dependency of that dependency doesn't really matter. The situation is the same, you manually updated a dependency and then your code broke. |
@xStrom sure, no argument about that. However, people need to stop thinking about go.mod as a way to lock versions. The module system assumes everything uses semver, and everything can be upgraded within semver rules. Therefore, if you publish something, that states in its module file it uses otherdep at version 1.2.3, you can not assume that all your downstream users will use otherdep, version 1.2.3. Just composing your code, with another module, that requests at least 1.2.4, will cause the state to be bumped to 1.2.4. And you can not declare in your module file it works with 1.2.3 and nothing else. You can declare it works starting with 1.2.3, and that 1.2.4 it incompatible, that will just make the module engine upgrade to 1.2.5 as soon as it is published if something else requires at least 1.2.4 So by publishing something, that uses otherdep 1.2.3, you make an implicit promise to your downstream users, that you will check your code works with all releases past 1.2.3, and blacklist them one by one if they don't (at which point it's probably less work to get into touch with otherdep's maintainer and convince him not to break compat) |
I get what you're saying and also I don't think you can mark anything as incompatible as a library. Last I checked only the top-level go.mod has the ability to exclude stuff. It's definitely true that the go modules system depends on people actually respecting semver. Personally I don't think it's that big of a problem. I've thus far successfully lived with the old Go compatibility guarantee where I just vendor the master tip of every library and rarely have I had issues. I think the new go modules system is a big upgrade over the old master tip system. Is it the be-all end-all version management system? Probably not, but it's a start. As far as reproducible builds go, they are achievable with the go modules system. If you have a fully defined go.mod and things work - then things will continue working. No new dependency update is ever going to creep into your project at a surprising moment. You can run go build 5 years down the line and it will work the same way as it did yesterday. This is a very strong property of the go modules system. You get to control when you want to deal with the drama of updating dependencies and figuring out which library failed to follow semver. |
Here is a half-baked thought. First, there is a new The question then is -- should there be some interplay between the questions here (about whether or not Perhaps Maybe the default for If so, maybe |
The immediately prior comment is the main thing I wanted to raise. This comment is a follow-up to that, but this is even less than 50% baked... Currently, there are some differences in how the Go 1.13 commands handle For example, Maybe that could be expanded to have different defaults for Using
If that was the approach, and let's say you run That glosses over what happens when a Also, maybe those two lists are not a good split of what commands would be in which list (e.g., maybe someone might argue Or maybe rather than the difference being the default Or maybe when the current code is out of sync with the current go.mod file, perhaps the semantics for Sorry, as I said, this is not fully baked. |
@thepudds, note that the Nor should they: I would argue that only |
I agree. Filed separately as #34822. |
Filed as #34829. |
That will hopefully be addressed by #33848. If it is not, please file a separate issue. |
I believe that the aforementioned issues address all of the actionable problems reported in this issue thread, but it's been a long thread so it's possible that I've missed one. We try to keep open issues in the Go issue tracker actionable and focused on a single problem or decision, and apart from the above issues this thread is not, so I'm going to close it out. Please do continue to file new issues for specific use-cases where the behavior of |
Change https://golang.org/cl/209037 mentions this issue: |
<rant>
This is quite honestly becoming (literally) rage-inducing so I'll keep it short...
Since the introduction of the package cache and modules,
go list
has gained some (IMO) nasty side-effects like downloading things from the internet and compiling (CGO) packages when all I did was ask it to print the import path of the current package.Additionally, package querying shouldn't result in updating any files. This coupled with the fact that
GOPATH/mod/...
is readonly means that if you're in a package inside the mod cache and rungo list
it might fail because it can't write togo.mod
(why is it updating the file?!?!?!).This script that creates a
go.mod
file with an extra empty line at the end demonstrates the latter issue:To make matters worse,
go/build
suddenly started callinggo list
so a simple operation like.Import(...FindOnly)
that used to take no more than a couple milliseconds, now takes several seconds for no good reason... all because thego
tool decided it was going download things from the internet, compile things and god knows what else... all manner of surprises I didn't ask for.Usually I'd just code my way around it with the power of NIH, but the behavior of
go/build
and package lookups and querying in general is un(der)-documented and I don't want to have to keep track of whatever new magic itmightwill gain in the future.I doubt any of this is ever going to be fixed, so it'd be nice if these things were documented so I could answer questions like "given an import path, how do I go about finding it in
GOPATH
,vendor
,module cache
,build cache
, etc.?" without having to rely on some broken black box.The text was updated successfully, but these errors were encountered: