问题
The classical way to declare a dependency's version in go mod is via
require (
k8s.io/api v0.17.4
k8s.io/apimachinery v0.17.4
k8s.io/cli-runtime v0.17.0
k8s.io/client-go v0.17.4
)
In the past (go <= 1.12 ?) this has been resolved to timestamp versions, but recently the versions are kept untouched.
However, I've also seen this technique to pin versions:
require (
k8s.io/api v0.17.4
k8s.io/apimachinery v0.17.4
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
k8s.io/code-generator v0.18.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
)
replace (
k8s.io/api => k8s.io/api v0.16.4
k8s.io/client-go => k8s.io/client-go v0.16.4
k8s.io/code-generator => k8s.io/code-generator v0.16.4
k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf
)
The question is why would one choose one approach over the other? Is the latter required to resolve conflicting versions coming from transitive dependencies? And if so, why shouldn't one add versions only to the replace()
clause from the very beginning to be precise (not only in the conflicting case)?
回答1:
A replace is helpful when you want to use a particular version of a dependency in the current module:
You might want to use that version because it's a fork with modifications you need.
require example.com/original v1.0.0 replace example.com/original => github.com/... v1.0.1
(Note: you can replace
v1.0.1
withmaster
(or another branch) and it will be replaced with a pseudo-version the next time youbuild
/test
/mod tidy
.)You may not be able to change minor versions of this particular dependency for some reason. Perhaps it requires extra testing to verify behavior or perhaps you've tried newer versions and they don't work.
You might be making changes to multiple projects, or you have multiple modules in a single repo, and you want to be able to make changes across all of the modules at the same time while developing.
In order for a replace to be meaningful, you need to be depending on the module you are replacing. You add dependencies in a go.mod
by using require
, so you can't only use replace
.
A replace
is extra work to maintain and replacing everything is not necessary in general. replace
should be used selectively, when necessary, like in the situations above.
Finally, adding a replace does not make the version selection more "precise." Adding the replace makes it more difficult for a dependency to update. A human will most likely need to go in and say, "Yes, we do want to upgrade this dependency," rather than let Minimum Version Selection decide when to upgrade a dependency, which could happen accidentally without a human noticing. As noted above, that could be bad for some projects.
来源:https://stackoverflow.com/questions/62005883/how-to-declare-golang-dependency-versions-best-in-go-mod