Go Module 的 6 类常规操作

339 阅读1分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

为当前 module 添加一个依赖

假设当前需要为项目增加一个新依赖:github.com/google/uuid

首先,更新源码

package main

import (
	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
)

func main() {
	logrus.Println("hello, go module mode")
	logrus.Println(uuid.NewString())
}

直接 build

会报错

$ go build 0_hello.go                                                                                                                                                                                                ░▒▓ INT ✘  12h 12m 9s   21:59:30  
0_hello.go:4:2: no required module provides package github.com/google/uuid; to add it:
        go get github.com/google/uuid
0_hello.go:5:2: no required module provides package github.com/sirupsen/logrus; to add it:
        go get github.com/sirupsen/logrus

报错提示也很明显了,使用 go get

go get

可以手动执行 go get 来添加某个依赖

$ go get github.com/google/uuid 
go: downloading github.com/google/uuid v1.3.0
go get: added github.com/google/uuid v1.3.0
  • go get 命令将新增的依赖包下载到了本地 module 缓存里
  • 并在 go.mod文件的 require 段中新增了一行内容
module example/hello

go 1.17


require (
	github.com/google/uuid v1.3.0 // indirect
)

表示当前项目依赖的 uuid 是 v1.3.0 版本

go mod tidy

其实前面的文章也有提到它,它会在执行构建前自动分析源码中的依赖变化,识别新增依赖包并下载它们

$ go mod tidy
go: finding module for package github.com/sirupsen/logrus
go: downloading github.com/sirupsen/logrus v1.8.1
go: found github.com/sirupsen/logrus in github.com/sirupsen/logrus v1.8.1
go: downloading golang.org/x/sys v0.0.0-20210514084401-e8d321eab015

总结

  • 对于添加某个依赖,go get 新增指定依赖项和 go mod tidy 自动分析并下载依赖项的效果是等价的
  • 但对于大型项目来说,go mod tidy 效率更高,更优选

升级/降级依赖版本

上一篇文章有讲到 Go Module 的版本号采用了语义版本规范,有了它可以很方便的对依赖项的版本进行升降级

go list

查询 logrus 存在的多个发布版本

$ go list -m -versions github.com/sirupsen/logrus   
github.com/sirupsen/logrus ... v0.11.5 v1.0.0 v1.0.1 v1.0.3 v1.0.4 v1.0.5 v1.0.6 v1.1.0 v1.1.1 v1.2.0 v1.3.0 v1.4.0 v1.4.1 v1.4.2 v1.5.0 v1.6.0 v1.7.0 v1.7.1 v1.8.0 v1.8.1

go get 获取指定版本的依赖项

$ go get github.com/sirupsen/logrus@v1.7.0
go: downloading github.com/sirupsen/logrus v1.7.0
go get: downgraded github.com/sirupsen/logrus v1.8.1 => v1.7.0

go mod tidy 获取指定版本的依赖项

需要首先用 go mod edit 命令告知要依赖的版本

$ go mod edit -require=github.com/sirupsen/logrus@v1.7.0
$ go mod tidy

Go Module 的依赖的主版本号都是 1

在 Go Module 构建模式下,当依赖的主版本号为 0 或 1 的时候,在 Go 源码中导入依赖包,不需要在包的导入路径上增加版本号

import github.com/user/repo/v0 等价于 import github.com/user/repo
import github.com/user/repo/v1 等价于 import github.com/user/rep

添加一个主版本号大于 1 的依赖

  • 如果要为 Go 项目添加主版本号大于 1 的依赖,就需要使用“语义导入版本”机制,在声明它的导入路径的基础上,加上版本号信息
  • 向 module-mode 项目添加 github.com/go-redis/redis 依赖包的 v7 版本为 🌰
package main

import (
	_ "github.com/go-redis/redis/v7"
	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
)

func main() {
	logrus.Println("hello, go module mode")
	logrus.Println(uuid.NewString())
}

go get

$ go get github.com/go-redis/redis/v7
go: downloading github.com/go-redis/redis/v7 v7.4.1
go: downloading github.com/go-redis/redis v6.15.9+incompatible
go get: added github.com/go-redis/redis/v7 v7.4.1

升级依赖版本

还是以上面的 redis 为🌰 ,将依赖从 v7 升级到 v8

import (
	_ "github.com/go-redis/redis/v8"
	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
)

再次 go get

$ go get github.com/go-redis/redis/v8                                                                                                                                                                                 ░▒▓ ✔  11:03:23  
go: downloading github.com/go-redis/redis/v8 v8.11.4
go: downloading github.com/cespare/xxhash/v2 v2.1.2
go: downloading github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
go: downloading gopkg.in/yaml.v2 v2.4.0
go get: added github.com/cespare/xxhash/v2 v2.1.2
go get: added github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
go get: added github.com/go-redis/redis/v8 v8.11.4

这样就能成功升级依赖版本了

移除依赖

还是以上面的 redis 为🌰 ,假设不需要 redis 这个依赖了

如果仅仅把源码中的 import 导入依赖语句删掉是不够的,在 go build 的时候还是会把 redis 一起构建,它是不会清理 go.mod 中多余的依赖项的

正确移除依赖

万能命令,go mod tidy,它会自动分析源码依赖,而且将不再使用的依赖从 go.mod 和 go.sum 中移除