文章目录
- [Go Modules是什么?](#Go Modules是什么?)
- [GOPATH 的工作模式](#GOPATH 的工作模式)
- [Go Modules模式](#Go Modules模式)
-
- [go mod命令](#go mod命令)
- [go mod环境变量](#go mod环境变量)
- [Go Modules初始化项目](#Go Modules初始化项目)
- 修改模块的版本依赖关系

Go Modules是什么?
Go Modules 是 Go 语言的依赖解决方案。
Go Modules 目前集成在 Go 的工具链中,只要安装了 Go,自然就可以使用 Go modules,Go modules 解决了 Go1.11 前的几个常见问题:
(1)Go 语言长久以来的依赖管理问题。
(2)"淘汰"现有的 GOPATH 的使用模式
(3)统一社区中的其它的依赖管理工具(提供迁移功能)
GOPATH 的工作模式
GOPATH下有三个文件夹:

bin :代表已经编译过的 go 语言的所有可执行程序。
pkg :存储默认文件,加快编译速度。
src:所有的源文件。
GOPATH 的弊端 :
(1)无版本控制概念。无法知道当前拉取的是哪个版本,也无法指定拉取自己的期望版本。
(2)无法同步一致第三方版本号。无法保证自己的版本与其他人的版本一致。
(3)无法指定当前项目引用的第三方版本号。
Go Modules模式
go mod命令
通过:go mod help
可以查看go mod命令
| 命令 | 作用 |
|---|---|
| go mod init | 生成go.mod文件 |
| go mod download | 下载go.mod 文件中指明的所有依赖 |
| go mod tidy | 整理现有的依赖 |
| go mod graph | 查看现有的依赖结构 |
| go mod edit | 编辑 go.mod 文件 |
| go mod vendor | 导出项目所有的依赖到vendor目录 |
| go mod verify | 校验一个模块是否被篡改过 |
| go mod why | 查看为什么需要依赖某模块 |
go mod环境变量
通过 go env 命令查看环境变量:

(1)GO111MODULE
Go语言提供了GO111MODULE这个环境变量来作为Gomodules的开关,其允许设置以下参数:
- auto:只要项目包含了go.mod文件的话启期Go modules,目前在Go1.11至Go1.14中仍然是默认值。
- on:启用Gomodules,推荐设置,将会是未来版本中的默认值。
- off:禁用Go modules,不推荐设置。
可以通过来设置:go env -w G0111MODULE=on
(2)GOPROXY
这个环境变量主要是用于设置Go模块代理(Gomoduleproxy),其作用是用于使Go在后续拉取模块版本时直接通过镜像站点来快速拉取。
GOPROXY 的默认值是:https://proxy.golang.org,direct
proxy·golang.org国内访问不了,需要设置国内的代理。
- 阿里云:
https://mirrors.aliyun.com/goproxy/ - 七牛云:
https://goproxy.cn,direct
direct:用于指示Go回源到模块版本的源地址去抓取(比如GitHub等)
(3)GOSUMDB
它的值是一个Go checksum database,用于在拉取模块版本时(无论是从源站拉取还是通过Gomodule proxy拉取)保证拉取到的模块版本数据未经过篡改,若发现不一致,也就是可能存在篡改,将会立即中止。
GOSUMDB 的默认值为:sum.golang.org,在国内也是无法访问的,但是GOSUMDB 可以被Go模块代理所代理。
因此我们可以通过设置GOPROXY来解决,而先前我们所设置的模块代理goproxy.cn就能支持代理sum.golang.org,所以这一个问题在设置GOPROXY后,你可以不需要过度关心。
(4)GONOPROXY、GONOSUMDB、GOPRIVATE
- GONOPROXY:通过设置GOPRIVATE即可
- GONOSUMDB:通过设置GOPRIVATE即可
- GOPRIVATE:
go env -w GOPRIVATE="git.example.com,github.com/aceld/zinx:表示git.example.com和github.com/aceld/zinx是私有仓库,不会进行GOPROXY下载和校验。
go evn -w GOPRIVATE="*example.com":表示所有模块路径为example.com的子域名,比如
git.example.com或者hello.example.com都不进行GOPROXY下载和校验。
Go Modules初始化项目
- 开启Go Modules
cmd
go env -w GO111MODULE=on
- 初始化项目
创建项目目录:在 E 盘下的 go_modules 文件夹下创建项目目录为 modules_test。
执行 Go modules 初始化,起一个当前项目的模块名称:go init github.com/go_modules/modules_test

初始化完成后,生成了 go.mod 文件:

打开 go.mod 文件:

- 在项目目录下编写源代码,创建 main.go 文件
go
package main
import (
"fmt"
"github.com/aceld/zinx/znet"
"github.com/aceld/zinx/ziface"
)
//ping test 自定义路由
type PingRouter struct {
znet.BaseRouter
}
//Ping Handle
func (this *PingRouter) Handle(request ziface.IRequest) {
//先读取客户端的数据
fmt.Println("recv from client : msgId=", request.GetMsgID(),
", data=", string(request.GetData()))
//再回写ping...ping...ping
err := request.GetConnection().SendBuffMsg(0, []byte("ping...ping...ping"))
if err != nil {
fmt.Println(err)
}
}
func main() {
//1 创建一个server句柄
s := znet.NewServer()
//2 配置路由
s.AddRouter(0, &PingRouter{})
//3 开启服务
s.Serve()
}
当前的 go_modules/modules_test 项目,依赖一个叫github.com/aceld/zinx库的,znet和ziface只是zinx的两个模块。
在 go_modules/modules_test 下执行:go get github.com/aceld/zinx/znet
此时 go.mod 文件被修改,并生成了 go.sum 文件:

(1)go.mod 文件:

- module:用于定义当前项目的模块路径
- go:标识当前Go版本
- require:当前项目依赖的一个特定的必须版本
// indirect:表示该模块为间接依赖。项目直接依赖的是 znet 包,间接依赖 zinx 包。
(2)go.sum 文件
go.sum 文件详细罗列了当前项目直接或间接依赖的所有模块版本 ,并写明了模块版本的 SHA-256 哈希值以备 Go 在今后的操作中保证项目所依赖的那些模块版本不会被篡改 。

一个模块路径可能有如下两种:
-
h1:hash情况:是 Go modules 将目标模块版本的 zip 文件开包后,针对所有包内文件依次进行 hash,然后再把它们的 hash 结果按照固定格式和算法组成总的 hash 值。

-
go.mod hash情况:对 go.mod 文件做的hash

h1 hash 和 go.mod hash 两者,要不就是同时存在,要不就是只存在 go.mod hash。当 Go 认为肯定用不到某个模块版本的时候就会省略它的 h1 hash,就会出现不存在 h1 hash,只存在 go.mod hash 的情况。
修改模块的版本依赖关系
当前依赖的zinx版本是最新版本:

如果想要使用以前的旧版本,可以通过在项目目录下执行:
cmd
go mod edit -replace=zinx@v1.2.7=zinx@v0.0.0-20200221135252-8a8954e75100

此时,go mod文件:

replace关键字:用于将一个模块版本替换为另外一个模块版本。