李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
GO
正文
14.Go module介绍
Leefs
2022-07-04 PM
1790℃
0条
[TOC] ### 前言 ![14.Go module介绍01.png](https://lilinchao.com/usr/uploads/2022/07/68596765.png) ### 一、概述 大多数语言都有“依赖”、“包”等概念,`Go`语言的依赖处理经历了几次变革。 最早的时候,`Go`所依赖的所有的第三方库都放在`GOPATH`这个目录下面从`v1.5`开始引入`vendor`模式,如果项目目录下有`vendor`目录,那么`go`工具链会优先使用`vendor`内的包进行编译、测试等 从`v1.11`开始,引入了`Go Module` 作为依赖解决方案,到`v1.14`宣布`Go Module`已经可以用于生产环境,到`v1.16`版本开始`Go Module`默认开启。 ### 二、GO PATH介绍 首先从 Golang 的环境配置说起,安装好之后,通过命令行来看下当前 Golang 的环境配置。 ```go go env ``` 有两个个比较重要的环境变量: - **GOROOT**:Golang 安装目录的路径,默认编译器程序和系统包,也可以放置三方包。 - **GOPATH**:当前工作目录,放置编译后二进制和 import 包时的搜索路径,一般有三个目录: bin、pkg、src。 + bin:用来存放编译后的可执行文件 + pkg:存储预编译的目标文件,以加快程序的后续编译速度。 + src:储所有.go文件或源代码。在编写 Go 应用程序,程序包和库时,一般会以`$GOPATH/src/github.com/foo/bar`的路径进行存放。 因此在使用 GOPATH 模式下,我们需要将应用代码存放在固定的`$GOPATH/src`目录下,并且如果执行go get来拉取外部依赖会自动下载并安装到`$GOPATH`目录下。 #### GOPATH模式的弊端 在 GOPATH 的 `$GOPATH/src` 下进行 `.go` 文件或源代码的存储,我们可以称其为 GOPATH 的模式,这个模式拥有一些弊端。 + A. **无版本控制概念**. 在执行go get的时候,你无法传达任何的版本信息的期望,也就是说你也无法知道自己当前更新的是哪一个版本,也无法通过指定来拉取自己所期望的具体版本。 + B.**无法同步一致第三方版本号**. 在运行 Go 应用程序的时候,你无法保证其它人与你所期望依赖的第三方库是相同的版本,也就是说在项目依赖库的管理上,你无法保证所有人的依赖版本都一致。 + C.**无法指定当前项目引用的第三方版本号**. 你没办法处理 v1、v2、v3 等等不同版本的引用问题,因为 GOPATH 模式下的导入路径都是一样的,都是github.com/foo/bar。 Go 语言官方从 Go1.11 起开始推进 Go modules(前身vgo),Go1.13 起不再推荐使用 GOPATH 的使用模式,Go modules 也渐趋稳定,因此新项目也没有必要继续使用GOPATH模式。 ### 三、go module #### 3.1 概念 `module`是一个相关`Go`包的集合,它是源代码更替和版本控制的单元。模块由源文件形成的`go.mod`文件的根目录定义,包含`go.mod`文件的目录也被称为模块根。`moudles`取代旧的的基于`GOPATH`方法来指定在工程中使用哪些源文件或导入包。模块路径是导入包的路径前缀,`go.mod`文件定义模块路径,并且列出了在项目构建过程中使用的特定版本。 ##### 优势 - 首先,研发者应该能够在任何目录下工作,而不仅仅是在GOPATH指定的目录。 - 可以安装依赖包的指定版本,而不是只能从master分支安装最新的版本。 - 可以导入同一个依赖包的多个版本。当我们老项目使用老版本,新项目使用新版本时会非常有用。 - 要有一个能够罗列当前项目所依赖包的列表。这个的好处是当我们发布项目时不用同时发布所依赖的包。Go能够根据该文件自动下载对应的包。 #### 3.2 go module相关命令 | 命令 | 介绍 | | :-------------: | :--------------------------------------: | | go mod init | 初始化项目依赖,生成go.mod文件 | | go mod download | 根据go.mod文件下载依赖 | | go mod tidy | 比对项目文件中引入的依赖与go.mod进行比对 | | go mod graph | 输出依赖关系图 | | go mod edit | 编辑go.mod文件 | | go mod vendor | 将项目的所有依赖导出至vendor目录 | | go mod verify | 检验一个依赖包是否被篡改过 | | go mod why | 解释为什么需要某个依赖 | #### 3.3 参数配置 + **GO111MODULE** Go语言提供了 GO111MODULE 这个环境变量来作为 Go modules 的开关,其允许设置以下参数: | 参数 | 说明 | | ---- | ------------------------------------------------------------ | | auto | 只要项目包含了 go.mod 文件的话启用 Go modules,目前在 Go1.11 至 Go1.14 中仍然是默认值。 | | on | 启用 Go modules,推荐设置,将会是Go1.16版本之后的默认值。 | | off | 禁用 Go modules,不推荐设置。 | + **GOPROXY** 这个环境变量主要是用于设置 Go 模块代理(Go module proxy),其作用是用于使 Go 在后续拉取模块版本时能够脱离传统的 VCS 方式,直接通过镜像站点来快速拉取。 GOPROXY 的默认值是:`https://proxy.golang.org,direct`,由于某些原因国内无法正常访问该地址,所以我们通常需要配置一个可访问的地址。目前社区使用比较多的有两个`https://goproxy.cn`和`https://goproxy.io`,当然如果你的公司有提供GOPROXY地址那么就直接使用。 设置GOPAROXY的命令如下: ```go go env -w GOPROXY=https://goproxy.cn,direct ``` GOPROXY 允许设置多个代理地址,多个地址之间需使用英文逗号 “,” 分隔。最后的 “direct” 是一个特殊指示符,用于指示 Go 回源到源地址去抓取(比如 GitHub 等)。当配置有多个代理地址时,如果第一个代理地址返回 404 或 410 错误时,Go 会自动尝试下一个代理地址,当遇见 “direct” 时触发回源,也就是回到源地址去抓取。 + **GOPRIVATE** 设置了GOPROXY 之后,go 命令就会从配置的代理地址拉取和校验依赖包。当我们在项目中引入了非公开的包(公司内部git仓库或 github 私有仓库等),此时便无法正常从代理拉取到这些非公开的依赖包,这个时候就需要配置 GOPRIVATE 环境变量。GOPRIVATE用来告诉 go 命令哪些仓库属于私有仓库,不必通过代理服务器拉取和校验。 GOPRIVATE 的值也可以设置多个,多个地址之间使用英文逗号 “,” 分隔。我们通常会把自己公司内部的代码仓库设置到 GOPRIVATE 中,例如: ```go $ go env -w GOPRIVATE="git.mycompany.com" ``` 这样在拉取以`git.mycompany.com`为路径前缀的依赖包时就能正常拉取了。 此外,如果公司内部自建了 GOPROXY 服务,那么我们可以通过设置 `GONOPROXY=none`,允许通内部代理拉取私有仓库的包。 #### 3.4 配置文件 + **go.mod 文件** 在初始化项目时,会生成一个 go.mod 文件,是启用了 Go modules 项目所必须的最重要的标识,同时也是 GO111MODULE 值为 auto 时的识别标识,它描述了当前项目(也就是当前模块)的元信息,每一行都以一个动词开头。 **示例文件** ```go module github.com/eddycjy/module-repo go 1.13 require ( example.com/apple v0.1.2 example.com/banana v1.2.3 example.com/banana/v2 v2.3.4 example.com/pear // indirect example.com/strawberry // incompatible ) exclude example.com/banana v1.2.4 replace example.com/apple v0.1.2 => example.com/fried v0.1.0 replace example.com/banana => example.com/fish ``` **说明** - **module**:用于定义当前项目的模块路径。 - **go**:用于标识当前模块的 Go 语言版本,值为初始化模块时的版本,目前来看还只是个标识作用。 - **require**:用于设置一个特定的模块版本。 - **exclude**:用于从使用中排除一个特定的模块版本。 - **replace**:用于将一个模块版本替换为另外一个模块版本。 另外你会发现 `example.com/pear` 的后面会有一个 indirect 标识,indirect 标识表示该模块为间接依赖,也就是在当前应用程序中的 import 语句中,并没有发现这个模块的明确引用,有可能是你先手动 go get 拉取下来的,也有可能是你所依赖的模块所依赖的,情况有好几种。 + **go.sum 文件** 在第一次拉取模块依赖后,会发现多出了一个 go.sum 文件,其详细罗列了当前项目直接或间接依赖的所有模块版本,并写明了那些模块版本的 SHA-256 哈希值以备 Go 在今后的操作中保证项目所依赖的那些模块版本不会被篡改。 ``` github.com/eddycjy/mquote v0.0.1 h1:4QHXKo7J8a6J/k8UA6CiHhswJQs0sm2foAQQUq8GFHM= github.com/eddycjy/mquote v0.0.1/go.mod h1:ZtlkDs7Mriynl7wsDQ4cU23okEtVYqHwl7F1eDh4qPg= github.com/eddycjy/mquote/module/tour v0.0.1 h1:cc+pgV0LnR8Fhou0zNHughT7IbSnLvfUZ+X3fvshrv8= github.com/eddycjy/mquote/module/tour v0.0.1/go.mod h1:8uL1FOiQJZ4/1hzqQ5mv4Sm7nJcwYu41F3nZmkiWx5I= ... ``` 可以看到一个模块路径可能有如下两种: ``` github.com/eddycjy/mquote v0.0.1 h1:4QHXKo7J8a6J/k8UA6CiHhswJQs0sm2foAQQUq8GFHM= github.com/eddycjy/mquote v0.0.1/go.mod h1:ZtlkDs7Mriynl7wsDQ4cU23okEtVYqHwl7F1eDh4qPg= ``` h1 hash 是 Go modules 将目标模块版本的 zip 文件开包后,针对所有包内文件依次进行 hash,然后再把它们的 hash 结果按照固定格式和算法组成总的 hash 值。 而 h1 hash 和 go.mod hash 两者,要不就是同时存在,要不就是只存在 go.mod hash。那什么情况下会不存在 h1 hash 呢,就是当 Go 认为肯定用不到某个模块版本的时候就会省略它的 h1 hash,就会出现不存在 h1 hash,只存在 go.mod hash 的情况。 #### 3.5 全局缓存 Go module 会把下载到本地的依赖包会以类似下面的形式保存在 `$GOPATH/pkg/mod`目录下,每个依赖包都会带有版本号进行区分,这样就允许在本地存在同一个包的多个不同版本。 ``` mod ├── cache ├── cloud.google.com ├── github.com └──q1mi ├── hello@v0.0.0-20210218074646-139b0bcd549d ├── hello@v0.1.1 └── hello@v0.1.0 ... ``` 如果想清除所有本地已缓存的依赖包数据,可以执行 `go clean -modcache` 命令。 #### 3.6 go get 升级 Golang 包的版本号管理一般都是:主版本、次要版本、修订版本(x.y.z)这种方式。 **使用 `go get` 进行升级有如下规则:** + `go get -u` 将会升级到最新的次要版本或者修订版本。 + `go get -u=patch` 将会升级到最新的修订版本。 + `go get package@version` 将会升级到指定的版本号。 + `go get` 如果有版本的更改,那么 `go.mod` 文件也会更改。 *附参考文章链接* *https://www.liwenzhou.com/posts/Go/11-package/#autoid-1-1-5* *https://blog.csdn.net/u011069013/article/details/110114319*
标签:
Golang基础
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2224.html
上一篇
13.Golang包介绍
下一篇
15.Golang流程控制
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
Quartz
Spark RDD
Jquery
设计模式
Livy
Shiro
Ubuntu
锁
Docker
Scala
ajax
线程池
CentOS
Golang
Azkaban
并发编程
容器深入研究
随笔
数据结构和算法
BurpSuite
LeetCode刷题
Hbase
JavaSE
序列化和反序列化
机器学习
JavaScript
哈希表
Yarn
Spark Core
Spark
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭