李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
GO
正文
14.Go module介绍
Leefs
2022-07-04 PM
1135℃
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
43
标签云
人工智能
栈
Typora
随笔
Nacos
数学
并发编程
Jquery
HDFS
Hive
Java工具类
字符串
Flink
SQL练习题
稀疏数组
MyBatis-Plus
机器学习
Jenkins
前端
Java阻塞队列
RSA加解密
SpringBoot
Golang
Spark SQL
SpringCloudAlibaba
Spark RDD
锁
序列化和反序列化
散列
Ubuntu
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞