Go Module
最后修改时间 2024 年 4 月 11 日
本文将介绍如何在 Golang 中使用 Modules。
Module 是一个文件树中存储的 Go 包的集合。
Modules 包含两个特定的文件:go.mod 和 go.sum。go.mod 定义了 module 路径和依赖需求。go.sum 是一个自动生成的依赖锁定文件。
Modules 使我们能够定义精确的依赖需求,并为多个环境设计可重现的构建。
第三方 Modules 从它们的仓库下载到 Module 缓存中。构建应用程序时,这些依赖项会从这些副本中加载。Module 缓存默认位于主目录的 go 子目录中。
go module 命令
go 工具提供了几个与 Modules 相关的命令。
- go mod init - 初始化当前目录中的新 Module
- go mod tidy - 添加缺失的 Module 并移除未使用的 Module
- go mod download - 将 Modules 下载到本地缓存
- go mod vendor - 为依赖项创建供应商副本
- go mod graph - 打印 Module 依赖图
- go mod verify - 验证依赖项是否包含预期内容
- go mod why - 解释为什么需要包或 Module
还有其他与 Go Modules 相关的命令。
go list -m 列出可用的 Modules。go get 安装依赖项并更新 go.mod 文件。go build 和 go test 命令根据需要向 go.mod 添加新的依赖项。
go mod init
go mod init 命令在当前目录中创建新的 Module。当前目录会创建一个新的 go.mod 文件;该文件必须不存在。
$ go mod init [module-path]
Module 路径是用于导入该 Module 所有包的前缀路径。开发者通常使用托管源代码的仓库 URL 作为 Module 路径。
$ go mod init com.zetcode/first go: creating new go.mod: module com.zetcode/first
创建一个具有 com.zetcode/first Module 路径的新 Module。
$ cat go.mod module com.zetcode/first go 1.17
这是 go.mod 文件的内容。我们有 Module 路径和 Go 版本。
go get 命令
使用 go get 命令安装依赖项。该命令会自动更新 go.mod 文件并创建 go.sum 文件。
$ go mod init com.zetcode/myprog
首先,我们创建一个 Module。
$ go get gonum.org/v1/gonum/stat go: downloading gonum.org/v1/gonum v0.9.3 go get: added gonum.org/v1/gonum v0.9.3
我们安装 Gonum 库。它是 Go 语言的一套数值库。
$ ls go.mod go.sum
我们在当前工作目录中有 go.mod 和 go.sum。
~/go/pkg/mod/gonum.org/v1/gonum@v0.9.3$ ls -1 appveyor.yml AUTHORS blas cmplxs CONDUCT.md CONTRIBUTING.md CONTRIBUTORS diff doc.go dsp floats go.mod GOPHER gopher.png gopher.svg go.sum graph integrate internal interp lapack LICENSE mat mathext num optimize README.md spatial stat THIRD_PARTY_LICENSES unit version.go
Gonum 库作为 Module 分发;默认情况下,它安装在用户主目录的 go 子目录中。
package main
import (
"fmt"
"math"
"gonum.org/v1/gonum/stat"
)
func main() {
xs := []float64{
12.44, 11.2, 34.5, 1.4, 6.7, 23.4,
}
fmt.Printf("data: %v\n", xs)
mean := stat.Mean(xs, nil)
variance := stat.Variance(xs, nil)
stddev := math.Sqrt(variance)
fmt.Printf("mean: %v\n", mean)
fmt.Printf("variance: %v\n", variance)
fmt.Printf("std-dev: %v\n", stddev)
}
我们有一个简单的示例,用于计算一些基本统计数据。
import (
"fmt"
"math"
"gonum.org/v1/gonum/stat"
)
我们获取 Module 的 stat 包。
$ go run first.go data: [12.44 11.2 34.5 1.4 6.7 23.4] mean: 14.94 variance: 145.12640000000002 std-dev: 12.046841909811883
$ go list -m all com.zetcode/myprog dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 gioui.org v0.0.0-20210308172011-57750fc8a0a6 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af github.com/boombuler/barcode v1.0.0 github.com/davecgh/go-spew v1.1.0 ...
使用 go list -m all,我们列出项目的所有依赖项。
依赖项管理 (Vendoring)
依赖项管理是一种满足项目依赖项的特定方式。与使用默认的 Module 缓存不同,依赖项会被下载,然后从 vendor 子目录加载。该目录是项目目录的一个子目录。
$ go mod vendor
go mod vendor 命令在主 Module 的根目录中创建一个名为 vendor 的目录。该命令还会创建 vendor/modules.txt 文件,其中包含供应商包列表以及它们被复制的 Module 版本。
$ go mod init com.zetcode/second $ go get github.com/bykof/gostradamus
我们创建一个项目并下载一个依赖项。gostradamus 是一个用于处理日期和时间的库。
package main
import (
"fmt"
"github.com/bykof/gostradamus"
)
func main() {
now := gostradamus.Now()
fmt.Println(now)
}
该示例打印当前日期时间。
$ go mod vendor
我们初始化依赖项管理。
$ ls go.mod go.sum second.go vendor
我们创建了 vendor 目录。
$ ls vendor/github.com/ bykof
它包含我们的依赖项。
来源
在本文中,我们讨论了 Go 中的 Modules。