How to declare golang dependency versions best in go.mod?

好久不见. 提交于 2020-08-10 04:49:08

问题


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 with master (or another branch) and it will be replaced with a pseudo-version the next time you build/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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!