golang module

这里整合下golang module使用中常见的问题。
项目迁移使用go module作为依赖管理工具
   这里简单整合流程:
   1) go mod init [module name]
     go项目使用诸如dep/glide作为管理工具向go module迁移时,go mod init会创建go.mod并自动完成从Godeps.json,Gopkg.lock配置中导入依赖。
   2)go mod tidy
   对于go.mod并未添加任何依赖时,go mod tidy会检索项目代码中import导入的依赖,下载最新的版本,并记录到go.mod中。如果go.mod中手动添加了依赖,go mod tidy并不会自动更新依赖版本。同时go mod tidy会移除go.mod中记录,但是并为在项目代码中import的依赖。因此,使用go.mod作为版本控制时,使用go mod tidy进行检查是非常值得推荐的。
   使用go mod tidy有一下几点需要注意:
           2.1 go mod tidy检索项目,找到未被记录在go.mod中的包时,首先会查找本地module cache(一般在go安装目录/pkg/mod),找到本地最新版本并引用,如果本地为找到,则会查找远程仓库,拉取package,并记录最新版本到go.mod中。本地module cache有可能为较老的版本。
           2.2 go.mod中// indirect标记含义。
              indirect表明当前包并未在当前module中直接引用。导致indirect原因有以下几种可能。
              - 使用go get获取并未在项目中import过的包,会被标记为indirect,如2.1所述,go mod tidy会自动从go.mod中移除。
              - 引入的依赖本身并没有go.mod,即并非使用module作为依赖管理工具,则这个包本身所有的依赖则被记录到父级go.mod文件中,并被标记为// indirect,这种情况,go mod tidy不会予以清除。
              - 使用go get -u [package path]更新包版本,-u参数不仅会更新直接升级的包,连带这个包中导入的package也会被更新。对于这种情况,需要注意几点:
                 go get -u并不会升级major版本(e.g v0.1.0, 分别为major, minor, pacth),而是只升级到最新的minor版本(go module语义版本后述),主版本对应较大的升级,而minor则可能是一些功能的添加更新,go get -u不会冒险升级主版本,另外go get -u=patch则会升级到最新的patch版本。如果是想要在module中引入多个major版本,参考https://blog.golang.org/v2-go-modules
                 go get -u升级package后,package中引入的module也会更新到最新minor版本,而新的minor版本则会记录到父级go.mod中,并标记为// indirect。

                 假设依赖关系 A依赖Bv0.1.0,Bv0.1.0依赖Cv0.1.0, 则go.mod文件如下:

A go.mod                  |  B go.mod
               |  
module A           | module B 
go 1.14           | go 1.14 
require B v0.1.0      |  require C v0.1.0  

                加入C最新版本更新到0.1.1,则在A项目中对B执行go get -u B,则A go.mod如下:

A go.mod

module A
go 1.14

require (
    C v0.1.1  // indirect       
    B v0.1.0
)

    此时A的go.mod中会添加对C的依赖,并标记为indirect,此时B中依赖则更新到C v0.1.1版本,而不再是B中go.mod记录的v0.1.0版本。举例:假如C更新了hello()接口,接口v0.1.0版本打印"hello", v0.1.1版本打印"world",而B中引用sayhello()调用C.hello()接口则使用的是Cv0.1.1版本。

              貌似采用go get -u影响有一些大,但是依照go module语义版本控制要求,版本接口都需要向下兼容。这里并不确定是否存在安全问题,也不再深究。如果在更新包时减少这种改变,可以使用go get [package]@version,选择具体版本进行更新。

 3)在使用go mod tidy进行go.mod包进行依赖调整后,再进行go build ./..或者go test ./...进行测试。

         由于其它包管理工具是基于独立的包或者整个repo,而非module,可能基于这种转换会存在转换完后版本并不完全相同的问题。这时候需要手动比较go.mod与原先配置是否存在不同,可以使用go mod why和go mod graph查找原因,然后使用go get手动更新包版本。

   4)go1.14中vendor向module迁移

        vendor向module迁移,在1.14版本中,默认go命令都会默认加上-mod=vendor,如go build等价go build -mod=vendor,此时若经过go mod tidy转换后的go.mod与vendor中对包的要求有差异,则go build会提示这种差异,此时可以选择使用go mod -mod=mod,选择忽略vendor目录,直接从module cache中加载module,或者使用go mod vendor去除这种差异,命令会查找vendor目录下所有的依赖,比较go.mod并生成到vendor/module.txt文件中,在此基础上使用go build(即go build -mod=vendor),会使用vendor下的依赖构建项目。

  

猜你喜欢

转载自www.cnblogs.com/myJune/p/12418934.html