① go进阶1-go mod使用入门
最近在梳理项目,排查隐患。有个go的核心项目一直使用的最传统的go path方式管理方式。是手动管理依赖的。这样不太合理。
首先vendor太大了,129M。其次,更重要的是依赖包没有版本控制,之前一直是我一个人在开发,后续如果多人开发就是个隐患。现计划升级成 go mod包管理。这里把涉及的知识点做一下汇总。
go moles 是 golang 1.11 新加的特性。moles的官方定义如下:
现在的方式是将开源的最新代码通过 go get 下载到本地的GOPATH 目录,然后需要时就去对应的 GOPATH 目录去查找了。这就不可避免带来一个问题,开源库总会升级,不同时间点下载的代码可能不一样。每次升级都要删除后重新引用,也增加了运维成本。
而go mod管理只需要一个go.mod文件即可。它通过在 go.mod 这个文件里记录了当前项目里所有依赖包的 git 仓库地址以及对应的版本号,来解决了包依赖管理的问题,后续在构建编译时,就会根据对应的版本号去拉取依赖包。也就是说只要我们维护了 gomod 文件,依赖问题就不再是问题了。
GO111MODULE 参数
GO111MODULE 有三个值:off, on和auto(默认值)
GO111MODULE=off,go命令行将不会支持mole功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
GO111MODULE=on,go命令行会使用moles,而一点也不会去GOPATH目录下查找。
GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用mole功能。如果有 go.mod 文件就启用。
下面设置go mod和go proxy
配置完如下
初始化 go.mod 文件
查看 go.mod 内容如下
现在把这个 mole 发布到github上,然后在别的项目中引用
在github上创建一个空仓库
项目上传到上述仓库(假设你已经完成本地ssh key到github)
执行完上面,相当于发布完成了。后续有人想用就可以直接 require 。
但这时候还没有加tag,所以没有版本管理。使用 tag 进行版本控制。
操作完,我们的mole就发布了一个v1.0.0的版本了。
tag是点,不可移动。branch是由点组成的线。后续可以基于某tag标签 checkout 一个版本,进行修改。不要在master上修改。
主项目引用远程mole
代码写好了,生成 go.mod 文件。
查看 go.mod
接下来就是享受 go.mod 便利的时候。一键操作。
1),将引用的开源包下载到 GOPSTH/pkg/mod 目录
2),同时生成了 gp.sum 。
go.mod: 可以理解为包管理文件。
go.sum: 可以理解为包的版本控制文件。更准确地来说,go.sum是一个构建状态跟踪文件。
接下来可以直接运行了。
假如fix一个bug,我们在v1.0.0 版本上进行修复。如 [email protected] => [email protected] 。更新引用包的版本:
修改 go.mod ,然后再次 go mod tidy 即可。会自动下载对应版本的开源包。非常方便。
上述就是go mod 的完整使用过程。go mod init、go mod tidy,基本就能解决很多依赖问题了。这也是 Go 官方一直提倡的简洁、优雅。
② 《快学 Go 语言》第 16 课 —— 包管理 GOPATH 和 Vendor
学习 Go 语言的模块管理功能,从 GOPATH 和 Vendor 机制开始。随着 Go 语言的发展,模块管理经历了三个阶段,分别是通过全局的 GOPATH 管理第三方包、通过 Vendor 机制将依赖包局部化,以及最新的 Go Mole 功能。
在模块管理的初期阶段,Go 语言使用全局的 GOPATH 路径来存放所有第三方依赖包。编译器在寻找包对象时,会优先检查 GOPATH 路径下的文件。通常,用户会将 GOPATH 设置为 ~/go 目录。了解三个关键子目录:src、pkg 和 bin,分别存放源代码、编译好的包对象和二进制可执行文件。
全局管理的 GOPATH 允许通过网站域名编写友好的包路径,使用 go get 指令从 GitHub、gopkg.in 和 golang.org 等网站拉取代码。此外,Go 语言提供了标准的模块结构,用户可以参照现有项目来构建自己的模块。
编写第一个模块时,需要在 GOPATH 中创建相应的目录结构,并编写代码。使用 go get 将模块提交至 GitHub。通过 go run 命令测试模块功能,然后使用 go get 更新模块至 GitHub。值得注意的是,Go 语言不推荐使用相对导入,通常建议采用绝对导入。
若遇到两个包路径的结尾相同,Go 语言支持导入语句名称替换功能来区分。此外,Go 还支持无名导入和匿名导入,但这些用法较少见且不建议使用。
Go 提供了三个指令来管理全局包:go build、go install 和 go get。go build 仅编译代码,go install 编译后安装包,而 go get 下载并编译包。在开发过程中,先执行 go build -i 可以加快运行速度。
为了解决不同项目依赖不同版本的第三方包问题,引入了 Vendor 机制。Vendor 目录将项目依赖的第三方包进行本地化管理,优先在 Vendor 中查找所需包。每个项目都有一个 Vendor 子目录,形成依赖树,但实际依赖深度通常较小。使用 Vendor 的限制是不能将依赖暴露到外部,以实现项目间版本隔离。
当需要引入具体版本的第三方包时,可以使用 Go 的依赖管理工具 Dep。Dep 管理项目配置文件 Godep.toml 和 Godep.lock,用于指定依赖规则和版本。初始化项目后,使用 dep ensure 指令确保依赖项与项目配置一致。更新版本或添加新依赖时,可执行相关 dep 命令。
尽管 Dep 工具复杂但使用简单,它支持下载新依赖、移除不使用的依赖,并确保依赖与配置文件完全匹配。Dep 虽然在 Go 社区中流行,但最终 Go 语言官方推荐使用 Go Mole 作为替代方案。