xdays

Golang依赖管理

August 17, 2019

关于Module

Module在1.11成为官方的依赖管理工具,虽然引起了不小的关于Go Module的争吵 ,但是应该就是以后主流的依赖管理工具了。

Module使用

当前版本1.12.8中go自动判断是否启用module功能,当位于GOPATH里时关闭,否则自动开启。

GO111MODULE=auto

新建一个module

mkdir example
cd example
go mod init github.com/xdays/example

然后你就基本不需要单独跑go get来获取依赖了,go rungo build等命令会根据你的import来自动下载依赖并确立依赖的版本,至于怎么确立的可以在跑完命令后参考go.mod文件的内容。

再者就是如果你更新了依赖版本,可以通过如下命令来清掉旧版本

go mod tidy

Module的管理

对于包管理者来说也可以通过上面的步骤切换到module上来,但是当需要更新大版本的时候就需要注意了。官方的原则是:

“If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.”

简而言之,更新大版本只需要如下几个步骤:

  1. 将上一个版本开个分支,比如v5,然后打上tag,继续维护
  2. 在master分支上开发不兼容的v6分支,然后打上对应的tag
  3. 最重要的是更新module的path,在最后添加上大版本的后缀,如果之前是github.com/xdays/example,那么更新之后就是github.com/xdays/example/v6,所以其实已经是不同的package了

更复杂的需求可以参考官方的Module文档

使用中遇到的问题

go-redis代码不兼容问题

问题

测试代码在这里redis-migrate,直接运行代码有问题

$ go run main.go
./main.go:105:55: cannot use &rangeBy (type *redis.ZRangeBy) as type redis.ZRangeBy in argument to srcClient.cmdable.ZRangeByScoreWithScores
./main.go:110:33: cannot use &z (type *redis.Z) as type redis.Z in argument to dstClient.cmdable.ZAdd

但是通过go get获取的redis-migrate却没有问题

go get github.com/xdays/go-utils/redis-migrate
redis-migrate                                            <aws:loop-staging>
found 5 keys
start migrating key test3 from scratch
set ttl to -1ns
start migrating key test5 from scratch
set ttl to -1ns
start migrating key test2 from scratch
set ttl to -1ns
start migrating key test1 from scratch
set ttl to -1ns
start migrating key test4 from scratch
set ttl to -1ns

分析

如果我在开启了module,这样import

import "github.com/go-redis/redis"

那么go module拿到的就是最小的稳定版本,go.mod里是这样的

github.com/go-redis/redis v6.15.3+incompatible

而如果我用传统的方式获取这个package,那我拿到的就是master分支的代码

go get github.com/go-redis/redis
cd $GOPATH/src/github.com/go-redis/redis
git branch

可以看到两种方式拿到的package的版本并不一样。

解决

把import的package路径改为

import "github.com/go-redis/redis/v7"

然后执行

go mod tidy

再看go.mod,已经更新到最新的版本了

github.com/go-redis/redis/v7 v7.0.0-beta.2

所以如果项目开启了module,在import依赖的时候要去看下依赖的go.mod对应的路径,看看是不是有版本声明的后缀。这是go-redis的版本声明


xdays

我是 xdays, 记录着我技术的成长,生活的点滴和感悟,能对你有所帮助那更好。