长沙网站排名优化价格wordpress page 分类
GoLang 中常用的包管理的方式
- 常用的有三种 
- Go Path
 - Go Vendor
 - Go Modules
 
 
关于 Go Modules
1 ) 概述
- Go的包管理,经过社区和官方的共同努力下,最终在百家争鸣后
 - Go官方在 2018.8 推出了go 1.11版本中的Go Modules,并且很快成为一统江湖的包管理方式
 - Go Modules已经成为目前最主流的包管理工具
 - 需要注意的是,go从1.13版本开始 Go Modules 被默认选择使用
 - 在go的1.11 和 go的1.12 版本中,需要我们手动开启 Go Modules
 
| 管理方式 | 版本 | 发布时间 | 
|---|---|---|
| GoPath 模式 | < 1.5 版本 | 2009.11.10 | 
| Go Vendor | >= 1.5 版本 | 2015.8.19 | 
| Go Modules | >=1.11 版本 | 2018.8.24 | 
- 关于Go Modules,我们必须要搞明白下面这几个问题 
- 第一个是 Go Modules 的用法
 - 第二个是 go.mod 文件是什么时候生成的,有什么作用,具体有哪些内容
 - go.sum 文件是什么时候生成的,有什么作用,具体有哪些内容,其中的哈希值是怎么计算的, 怎么实现包校验的
 
 
2 ) Go Modules 用法
- 在go1.11的时候就发布了 Go Modules, 但是功能默认是关闭的,直到go的1.13版本才开始开启
 - 所以在go 1.11 和 go 1.12 版本中,我们需要通过go提供的变量,
GO111MODULE来开启 Go Modules- 这里跟之前的 Go Vendor 里面开启 govendor 的环境变量
 - 即:
GO15VENDOREXPERIMENT这个环境变量类似 
 GO111MODULE也属于go的阶段性变量- 通常在某个功能发布之初的几个版本,是需要手动去开启的
 - 等稳定下来,被开发者接受之后,会在后续的版本中默认开启
 
GO111MODULE,它有三个值- 第一个是 
on, 它表示开启 Go Modules - 第二个是 
off它表示关闭 Go Modules - 第三个是 
auto 
- 第一个是 
 - 当项目路径在
Go Path目录外部时- 如果你设置的是 
auto的话,我们这个GO111MODULE就会被设置成on 
 - 如果你设置的是 
 - 那当项目路径在 Go Path内部时 
- 即使存在 go.mod 文件, 也会将 
GO111MODULE设置成off 
 - 即使存在 go.mod 文件, 也会将 
 - 在Unix环境下(Linux, MacOS) 
- 需要把 
GO111MODULE设置成on,然后通过export将这个环境变量导出 export GO111MODULE=on
 - 需要把 
 - 在Windows环境 
- 我们可以通过 
set命令将GO111MODULE设置成on- $ 
set GO111MODULE=on 
 - $ 
 - 当然直接修改 Go 的 Path 环境变量也是可以的
 
 - 我们可以通过 
 - 还有一种方式是两种类型的操作系统都可以支持的 
- 我们可以通过 $ 
go env -w GO111MODULE=on - 加上 
-w参数来将这个GO111MODULE设置成on - 如果没有任何输出就是正常了
 - 注意,我们在执行上面这个命令的时候可能会抛出一个 
warning - 这个waring的意思, 就是说我们不能通过这个 
go env指令去覆盖我们环境变量的设置 - 也就是说,如果我们在环境变量里面已经设置了 
GO111MODULE这个环境变量 - 我们就需要去改环境变量里面这个 
GO111MODULE这个值,而不能通过命令的方式去设置 - 通常这些环境变量可能会在 
/etc/profile文件里- 或者是 
~/bash.profile文件里 - 或者是 
/etc/.bashrc文件里 - 或者是 
~/.bashrc文件里 - 或者是 
~/.profile文件里 
 - 需要注意的是,仅仅设置 
GO111MODULE,这个环境变量为on - 并不能代表项目就使用了 Go Modules 方式来管理包
 
 - 我们可以通过 $ 
 - 我们使用 $ 
go mod init将项目初始化成一个 Go Modules 工程 - 这个命令需要在项目的根目录下执行执行成功后,在当前目录下面生成一个 
go.mod的文件 
3 ) go mod 的具体用法
- 需要准备好环境,go版本 需要 >= 1.11 
- 如果go的版本没有到 1.13, 就需要将 
GO111MODULE设置成on - 查看我们当前使用的go版本,通过 $ 
go version 
 - 如果go的版本没有到 1.13, 就需要将 
 - 之后,可能需要设置go代理 
- 如果我们是开发环境,我们可以直接在这个编辑器IDE上进行设置,比如 GoLand
 - 在这个编辑器上,file / settings里面,就可以对这个go的环境变量进行配置
 - 可以找到Go Modules 
- 需要勾选这个 
EnableGo modules integration - 填入 Environment, 设置 Go Path 和 Go Proxy
 - GOPROXY https://goproxy.cn/,https://mirrors.aliyun.com/goproxy/,direct
 - 这里 direct的意思是当从上面两个途径无法获取,就从源码获取
 - GOPRIVATE 这个变量是内部包的配置,一般在公司部署的私网内的地址
 
 - 需要勾选这个 
 
 - 在生产环境中的设置 
- 比如在Unix环境下 
- 我们可以通过将下面
 export GOPROXY https://goproxy.cn/,https://mirrors.aliyun.com/goproxy/,direct- 放入 
/etc/profile里面 
 - 在Windows下,通过 set 指令设置 GOPROXY 
- $ 
set GOPROXY=https://goproxy.cn/,https://mirrors.aliyun.com/goproxy/,direct 
 - $ 
 - 也支持 $ 
go env -w GOPROXY=https://goproxy.cn/,https://mirrors.aliyun.com/goproxy/,direct 
 - 比如在Unix环境下 
 
4 ) 工程示例
- $ 
mkdir go-mod-test && cd go-mod-test目录, 仅作为示例 - $ 
go mod init go-mod创建一个go-mod工程目录 - 可看到里面生成一个 go.mod 文件
 - 在这里就可以编写程序了,$ 
touch main.gopackage mainimport 'github.com/astaxie/beego/logs'func main() {logs.Warn('demo') } - 现在解决 第三方包 引用的问题, 到工程根目录中执行
 - $ 
go mod tidy- 这时候就会自动找到项目以来的包
 - 解决工程中包依赖的关系,如果缺少包,则下载并维护信息到 go.mod
 - 如果没有用的,则移除
 
 - 执行 
go run main.go正常输出 - 在 go.mod 下又生成了 go.sum的文件 
- 这里写的是工程所有直接依赖包和间接依赖包
 
 go mod download- 下载依赖包到本地缓存
 - 如果 go.mod 和 go.sum 已经包含依赖包的信息,而且依赖包还没有下载到本地
 - 这个指令会把依赖包下载到本地
 
go mod vendor- 为了兼容 go vendor 模式
 - 在 go mod 发布之前,go vender 使用是比较普遍的
 - go mod 也支持将依赖包通过我们这个go mod vender 指令复制到我们项目 vendor 目录当中
 - 可以看到我们当前这个项目里面是没有 vendor 目录的
 - 那我们在这个项目的根目录里面,执行 
go mod vendor- 刷新一下,我们可以看到它就为我们生成的一个vendor目录
 - 在 vendor 里面还有一个 modules.txt 文件
 - 这个文件记录了我们当前这个venders里面依赖的包以及包的版本信息。
 
 
- 那上面四个指令是最常用的,还有一些其他指令 
- 比如 $ 
go help mod可以看到我们go mod支持的一些指令 - 这里面包括还有一些 
go mod graph,go mod why, 以及go mod verify - 这些是查看和校验依赖的一些指令
 go mod edit, 我们可以用来编辑这个 go.mod 文件, 平时也很少使用, 我们了解即可
 - 比如 $ 
 
5 ) 关于 go.mod 和 go.sum
- 接下来需要重点了解两个文件 
-  
1 ) go.mod
- 这个文件里面主要是描述了模块的一些属性
 - 包括它的其他模块的go版本的依赖的信息 
- 里面第一行就是 module 的name,这个name一般使用 git仓库上的路径
 - 第二行是版本信息,项目依赖的最低版本要求,只是获取当前go版本的信息
 - 第三行,require 指令,包含导入的 非工程项目内的包
 - 后面都是 require
 - 工程依赖包有直接依赖包,如beego, 还有间接依赖包 
- 所谓间接依赖包就是直接依赖包的依赖包
 - 如果beego中需要依赖一些包,有一些包没有 go.mod 文件则会添加到工程的 go.mod中
 - 并且生成一个尾版本号 
- 尾版本号格式: 版本号 - UTC的提交时间(提交到github的时间) - commit 哈希的前缀
 
 
 
 
 -  
2 ) go.sum
- 在触发项目编译后生成,如 
go build,go run等指令 - 里面详细罗列了项目直接或间接依赖的所有模块的版本
 - 每一条包含了模块依赖的路径,导入的版本和哈希值
 - 每个依赖包有可能有多条信息 
- 一种是有 
go mod标识,后面哈希值是go.mod的哈希 - 另一种没有,则后面的哈希是包的每一个文件的哈希
 
 - 一种是有 
 - 实现包的校验 
- 当我们拿到某个项目的源代码,并尝试在构地进行构建的时候
 - go命令会从本地缓存中去查找所有 go.mod 中记录的依赖包
 - 并且会计算出本地依赖包的哈希值
 - 然后与我们 go.sum 文件中的记录进行对比, 也就是说
 - 它会检测某地缓存中使用的依赖包的版本是否满足项目中 go.sum 文件中期望的版本
 - 如果不满足,就说明本地缓存目录当中的依赖包版本和项目中go.sum文件记录的版本的哈希值是不一致的
 - 这个时候构建就会被拒绝。
 - 这样就可以确保相同的依赖包在任何环境使用这些依赖包的源码,它都是一样的
 - 依赖包中任何一个文件,包括 go.mod 的改动,都会改变它整体的哈希值
 - 在 go.sum 中记录额外的 go.mod 的文件,就是为了在计算这个依赖树的时候
 - 不用去下载完整的依赖包版本,只根据 go.mod 就可以计算出这个依赖信息
 - 主要目的就是加快这个依赖包的校验
 - 那每条记录的哈希值, 都有一个表示的哈希算法的一个h1的哈希算法。
 - 这个哈希算法是由SHA-256计算出来的
 - 那模块版本的SHA-256的哈希值主要是用来校验当前缓存的模块
 - 用来准备go在今后的操作过程中,保证项目中所有的依赖的那些模块版本都不会被篡改
 - 在每次我们构建项目发现有模块缺少的时候,如果在缓存中不存在
 - 那就需要下载并且计算这个包的哈希
 - 并且添加到 go.sum当中,如果缓存中已经存在,就需要匹配 go.sum 中已有的记录
 - 需要注意的是,在每次缺少模块的时候,也就是说我们需要的依赖包
 - 它不在 go.sum 文件当中,而且是一个公网可下载的包
 - go命令就会去go的校验数据库获取模块的校验和,它的默认配置是这个 sum.golang.org
 - 我们也可以使用中国大陆官方的这个校验数据库 sum.golang.google.cn
 - 这个校验数据库,会查询并获取这个模块的校验和
 - 如果下载的这个模块的校验和与它计算出来的校验和不匹配
 - 那我们的 go mod 命令就没办法成功执行, 那如果能够匹配
 - 就会把校验和写到go.sum文件当中
 - 这里有三种情况,它不会对依赖包做哈希校验 
- 第一种, 就是我们配置的这个 GOPRIVATE 匹配到的包 
- 当我们配置的 GO PRIVATE 这个环境变量被我们 GO PRIVATE 匹配到的这些模块包就不会check sum校验
 - GO PRIVATE 这个变量主要是用来设置我们内部的一些包, 不走 GO PROXY 配置的代理
 - 因为内部的包,基于代码安全的考虑,都不会上传到我们的github上面
 
 - 第二个, 就是我们可以通过 
go mod vendor命令将依赖包全部下载到我们工程的根目录下的 vendor 目录下面- 它可以用来做离线编译
 - 打包到 vendor 目录中的包也不会再做哈希校验
 
 - 第三个, 就是 
GOSUMDB设置为off的时候- 所有的包都不会做包校验,相当于关闭了我们这个go sum的校验
 
 
 - 第一种, 就是我们配置的这个 GOPRIVATE 匹配到的包 
 
 
 - 在触发项目编译后生成,如 
 -  
需要注意的是,同一个模块版本的数据只会缓存一份。那所有其他模块呢都会共享使用。
 -  
如果你希望清除当前已经缓存的模块的版本数据,可以执行这个 $
go clean -modcache 
 -  
 
6 ) go.mod 和 go.sum 对比
- 为什么我们看到的 go.sum 文件中记录的依赖包的版本数量会比go.mod 文件要多很多
 - go.mod 记录的是直接依赖的依赖包版本,直接依赖包版本,不含 go.mod 文件时,才记录构建依赖赖的版本
 - go.sum则是要记录构建依赖到的所有依赖包的版本,它包括直接依赖包和间接依赖包
 
7 )关闭依赖包校验
- 如果不希望进行依赖包校验,可以关闭
 - 可以将这个
GOSUMDB设置成off就可以关闭我们当前的go sum校验- $ 
go env -w GOSUMDB=off - 或 将环境变量添加到 
/etc/profile 
 - $ 
 
8 ) 依赖包的存储对比
- Go Path 模式下和 Go Modules 模式下,依赖包的存储路径是不一样的
 - 在 Go Path 模式下,依赖包存储在这个 
$GOPATH/src - 这个目录下只保存特定依赖包的一个版本
 - 我们通过 
go get下载的包,也包含完整的仓库信息的,也就是包含了 .git 的目录 - 而我们在 
GOMODULES模式下,依赖包会存储在这个$GOPATH/pkg/mod下面- 而且这个目录下面可以存储特定依赖包的多个版本
 - 每个版本会占用一个目录,那这个目录里面,只包含依赖包文件,不包含 .git 的目录
 
 
Go编码原则与建议
- 构建go项目的时候,也需要遵循一些原则和规范性的建议
 - 1 ) 我们一个目录名,下面只能有一个package,否则我们的编译器就会报错
 - 2 ) 建议一个package名的内容放在一个目录下面, 方便我们做项目管理
 - 3 ) 建议目录名和package名保持一致,这样也能方便我们对项目进行管理
 
