> For the complete documentation index, see [llms.txt](https://yangsx95.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yangsx95.gitbook.io/notes/programming-language/golang/build-tools/gomodule.md).

# Go Module

自从 Go 官方从去年推出 1.11 之后，增加新的依赖管理模块并且更加易于管理项目中所需要的模块。模块是存储在文件树中的 Go 包的集合，其根目录中包含 go.mod 文件。 go.mod 文件定义了模块的模块路径，它也是用于根目录的导入路径，以及它的依赖性要求。每个依赖性要求都被写为模块路径和特定语义版本。

从 Go 1.11 开始，Go 允许在 `$GOPATH/src` 外的任何目录下使用 `go.mod` 创建项目。在 `$GOPATH/src` 中，为了兼容性，Go 命令仍然在旧的 `GOPATH` 模式下运行。从 Go 1.13 开始，模块模式将成为默认模式。

## 启用Go Modules

```shell
go env -w GO111MODULE=on # 111代表版本1.11
go env -w GOPROXY=https://goproxy.io # 配置代理
# go env -w GOPROXY=https://goproxy.cn
```

> 使用 `go env` 可以查询所有的环境变量，用于确认当前的配置

## 创建一个新模块

```shell
# 创建项目目录
$ mkdir backend && cd backend

# 初始化模块，将会生成go.mod文件
$ go mod init backend
go: creating new go.mod: module backend

$ ll
total 8
-rw-r--r--  1 yangsx  staff    24B  9 17 13:32 go.mod

$ cat go.mod
module backend # init命令指定的项目名称

go 1.17 # 当前项目版本号
```

## 添加依赖项

```shell
# 安装依赖
$ go get -u github.com/gin-gonic/gin
go: downloading golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
go: downloading golang.org/x/sys v0.0.0-20211205182925-97ca703d548d
go get: added github.com/gin-contrib/sse v0.1.0
go get: added github.com/gin-gonic/gin v1.7.7
go get: added github.com/go-playground/locales v0.14.0
go get: added github.com/go-playground/universal-translator v0.18.0
go get: added github.com/go-playground/validator/v10 v10.9.0
go get: added github.com/golang/protobuf v1.5.2
go get: added github.com/json-iterator/go v1.1.12
go get: added github.com/leodido/go-urn v1.2.1
go get: added github.com/mattn/go-isatty v0.0.14
go get: added github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
go get: added github.com/modern-go/reflect2 v1.0.2
go get: added github.com/ugorji/go/codec v1.2.6
go get: added golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
go get: added golang.org/x/sys v0.0.0-20211205182925-97ca703d548d
go get: added golang.org/x/text v0.3.7
go get: added google.golang.org/protobuf v1.27.1
go get: added gopkg.in/yaml.v2 v2.4.0

# 查看go.mod
$ cat go.mod
module backend

go 1.17

require (
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/gin-gonic/gin v1.7.7 // indirect
	github.com/go-playground/locales v0.14.0 // indirect
	github.com/go-playground/universal-translator v0.18.0 // indirect
	github.com/go-playground/validator/v10 v10.9.0 // indirect
	github.com/golang/protobuf v1.5.2 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/leodido/go-urn v1.2.1 // indirect
	github.com/mattn/go-isatty v0.0.14 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/ugorji/go/codec v1.2.6 // indirect
	golang.org/x/crypto v0.0.0-20211202192323-5770296d904e // indirect
	golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
	golang.org/x/text v0.3.7 // indirect
	google.golang.org/protobuf v1.27.1 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
)

# 导入gin并使用他启动一个web服务器
$ echo 'package main

import "github.com/gin-gonic/gin"

func main() {
        r := gin.Default()
        r.GET("/ping", func(c *gin.Context) {
                c.JSON(200, gin.H{
                        "message": "pong",
                })
        })
        r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}' > main.go

$ ll
total 40
-rw-r--r--  1 yangsx  staff   933B 12  7 09:07 go.mod
-rw-r--r--  1 yangsx  staff   9.0K 12  7 09:07 go.sum
-rw-r--r--  1 yangsx  staff   252B 12  7 09:09 main.go

# 执行main函数，启动服务器
$ go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
```

## indirect注释

在执行命令`go mod tidy`时，Go module 会自动整理`go.mod` 文件，如果有必要会在部分依赖包的后面增加`// indirect`注释。一般而言，被添加注释的包肯定是间接依赖的包，而没有添加`// indirect`注释的包则是直接依赖的包，即明确的出现在某个`import`语句中。

## 查询该mod的依赖项

```shell
# 查询所有依赖项，可以看到依赖坐标以及版本
# 这里的大部分依赖都是gin依赖的
$ go list -m all
backend
github.com/creack/pty v1.1.9
github.com/davecgh/go-spew v1.1.1
github.com/gin-contrib/sse v0.1.0
github.com/gin-gonic/gin v1.7.7
github.com/go-playground/assert/v2 v2.0.1
github.com/go-playground/locales v0.14.0
github.com/go-playground/universal-translator v0.18.0
github.com/go-playground/validator/v10 v10.9.0
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.5
github.com/google/gofuzz v1.0.0
github.com/json-iterator/go v1.1.12
github.com/kr/pretty v0.3.0
github.com/kr/pty v1.1.1
github.com/kr/text v0.2.0
github.com/leodido/go-urn v1.2.1
github.com/mattn/go-isatty v0.0.14
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/modern-go/reflect2 v1.0.2
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e
github.com/pmezard/go-difflib v1.0.0
github.com/rogpeppe/go-internal v1.8.0
github.com/stretchr/objx v0.1.0
github.com/stretchr/testify v1.7.0
github.com/ugorji/go v1.2.6
github.com/ugorji/go/codec v1.2.6
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
golang.org/x/text v0.3.7
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
google.golang.org/protobuf v1.27.1
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
gopkg.in/errgo.v2 v2.1.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
```

## 升级/回退依赖

```shell
# 查询gin的所有版本
$ go list -m -versions github.com/gin-gonic/gin
github.com/gin-gonic/gin v1.1.1 v1.1.2 v1.1.3 v1.1.4 v1.3.0 v1.4.0 v1.5.0 v1.6.0 v1.6.1 v1.6.2 v1.6.3 v1.7.0 v1.7.1 v1.7.2 v1.7.3 v1.7.4

# 升级/回退到某个版本
$ go get github.com/gin-gonic/gin@v1.1.4
go: downloading github.com/gin-gonic/gin v1.1.4
go: downloading golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
go: downloading gopkg.in/go-playground/validator.v8 v8.18.2
go: downloading github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739
go get: downgraded github.com/gin-gonic/gin v1.7.4 => v1.1.4
go get: added github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739
go get: added gopkg.in/go-playground/validator.v8 v8.18.2

# 查看 go.mod 可以发现gin已经被回退了
$ cat go.mod
module backend

go 1.16

require (
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/gin-gonic/gin v1.1.4 // indirect ************** 回退到了1.1.4 *****************
	github.com/go-playground/validator/v10 v10.4.1 // indirect
	github.com/golang/protobuf v1.3.3 // indirect
	github.com/json-iterator/go v1.1.9 // indirect
	github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739 // indirect
	github.com/mattn/go-isatty v0.0.12 // indirect
	github.com/ugorji/go v1.1.7 // indirect
	gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
	gopkg.in/yaml.v2 v2.2.8 // indirect
)
```

## 整理依赖项

如果项目中的一些依赖没有下载，或者有一些代码没有使用到的依赖，可以使用如下方式对依赖整理：

```shell
$ go mod tidy
go: finding module for package gopkg.in/go-playground/assert.v1
go: downloading gopkg.in/go-playground/assert.v1 v1.2.1
go: found gopkg.in/go-playground/assert.v1 in gopkg.in/go-playground/assert.v1 v1.2.1
```

## 下载依赖项

下载依赖到本地的cache路径，cache路径为`GOMODCACHE`:

```shell
$ go env | grep GOMODCACHE
GOMODCACHE="/Users/yangsx/go/pkg/mod"
```

## 排除/替换依赖

```go
module my/thing // 定义模块路径
go 1.12 // 设置预期的语言版本
require other/thing v1.0.2 
require new/thing/v2 v2.3.4 // indirect
require（ //  要求给定版本或更高版本的特定模块
  new/thing v2.3.4
  old/thing v0.0.0-20190603091049-60506f45cf65
）
exclude old/thing v1.2.3 // 排除特定版本模块的使用，不允许的模块版本被视为不可用，并且查询无法返回
replace bad/thing v1.4.5 => good/thing v1.4.5  // 使用不同的模块版本替换原有模块版本
```

或者使用`go mod edit`命令进行操作。

## 版本管理文件：go.sum

主要为了防止包被恶意篡改，比如有一天`gin`的`1.14.1`的版本在不知情的情况下被恶意修改了，这时，虽然路径与版本号没变，但是预期hash变化了，就会被`go mod verify`发现。

```shell
$ cat go.sum
# 由  模块导入路径 模块版本 预期hash 三个部分组成
# 在每次缺少模块时，如果缓存中不存在，则需要下载并计算其哈希添加到 go.sum 中；
# 如果缓存中存在，则需要匹配 go.sum 中的已有条目。
# 这样，构建软件的用户就可以使用哈希验证其构建是否跟你的构建相同（go mod verify），
# 而无论他们怎样获取依赖项，都可以得到相同的版本。同时也保证了项目依赖不会发生预料之外的恶意修改和其他问题。
# 这也是为什么要将 go.sum 文件加入版本管理（Git）的原因。

再加上 Go Modules 选择的是最小版本选择策略（默认使用构建中涉及的每个模块的最旧允许版本，使得新版本的发布对构建没有影响）就可以实现可重现的构建（在重复构建时产生相同的结果）。
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-gonic/gin v1.1.4 h1:XLaCFbU39SSGRQrEeP7Z7mM3lvRqC4vE5tEaVdLDdSE=
github.com/gin-gonic/gin v1.1.4/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739 h1:ykXz+pRRTibcSjG1yRhpdSHInF8yZY/mfn+Rz2Nd1rE=
github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739/go.mod h1:zUx1mhth20V3VKgL5jbd1BSQcW4Fy6Qs4PZvQwRFwzM=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=


$ go mod verify
all modules verified
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yangsx95.gitbook.io/notes/programming-language/golang/build-tools/gomodule.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
