详解Go module的介绍及使用

Go1.1.1版本发布(2018-08-24发布)已经过去几天,从官方的博客中看到,有两个比较突出的特色,一个就是今天讲的module,模块概念。目前该功能还在试验阶段,有些地方还需要不断的进行完善。在官方正式宣布之前,打算不断修正这种支持。到时候就可以移除对GOPATHgo get命令的支持。
如果你想现在想就试试这个新功能module,需要你将你的代码仓库放到GOPATH/src目录之外。然后在那个目录下创建一个go.mod文件,从文件树中运行go命令。

主要概念介绍

module是一个相关Go包的集合,它是源代码更替和版本控制的单元。模块由源文件形成的go.mod文件的根目录定义,包含go.mod文件的目录也被称为模块根。moudles取代旧的的基于GOPATH方法来指定在工程中使用哪些源文件或导入包。模块路径是导入包的路径前缀,go.mod文件定义模块路径,并且列出了在项目构建过程中使用的特定版本。

go.mod文件

go.mod文件定义module路径以及列出其他需要在build时引入的模块的特定的版本。例如下面的例子中,go.mod声明example.com/m路径时module的根目录,同时也声明了module依赖特定版本的golang.org/x/textgopkg.in/yaml.v2

module example.com/m

require (
  golang.org/x/text v0.3.0
  gopkg.in/yaml.v2 v2.1.0
)

go.mod文件还可以指定要替换和排除的版本,命令行会自动根据go.mod文件来维护需求声明中的版本。如果想获取更多的有关go.mod文件的介绍,可以使用命令go help go.mod
go.mod文件用//注释,而不用/**/。文件的每行都有一条指令,由一个动作加上参数组成。例如:

module my/thing
require other/thing 	v1.0.2
require new/thing 		v2.3.4
exclude old/thing 		v1.2.3
replace bad/thing 		v1.4.5 	=> good/thing v1.4.5

上面三个动词requireexcludereplace分别表示:项目需要的依赖包及版本、排除某些包的特别版本、取代当前项目中的某些依赖包。
相同动作的命令可以放到一个动词+括号组成的结构中,例如:

require (
  new/thing v2.3.4
  old/thing v1.2.3
)

其他命令的支持

旧的版本,构建编译命令go build中的参数没有-mod参数,最新的版本现在多了这个,用来对go.mod文件进行更新或其他使用控制。形式如:go build -mod [mode],其中mode有以下几种取值:readonlyreleasevendor。当执行go build -mod=vendor的时候,会在生成可执行文件的同时将项目的依赖包放到主模块的vendor目录下。
go get -m [packages]会将下载的依赖包放到GOPATH/pkg/mod目录下,并且将依赖写入到go.mod文件。go get -u=patch会更新主模块下的所有依赖包。
如果遇到不熟悉的导入包,任何可以查找包含该引入包模块的go命令,都会自动将该模块的最新版本添加到go.mod文件中。同时也会添加缺失的模块,以及删除无用的module。例如:go build, go test或者go list命令。另外,有一个专门的命令go mod tidy,用来查看和添加缺失的module需求声明以及移除不必要的。
go.mod文件是可读,也是可编辑的。go命令行会自动更新go.mod文件来维持一个标准格式以及精确的引入声明。

Go mod命令

Go mod提供了一系列操作modules的命令,记住,所有的go命令中现在已经内置了对module的支持,而不仅仅是go mod命令。例如使用go get时,会经常自动在后台添加、移除、升级、降级依赖包版本。
命令语法:go mod <command> [arguments]Go mod提供的命令有下面几个,对于比较常用的命令进行详细说明。

download        //下载模块到本地缓存,具体可以通过命令go env查看,其中环境变量GOCACHE就是缓存的地址,如果该文件夹的内容太大,可以通过命令go clean -cache
edit          //从工具或脚本中编辑go.mod文件
graph          //打印模块需求图
init          //在当前目录下初始化新的模块
tidy          //添加缺失的模块以及移除无用的模块
verify         //验证依赖项是否达到预期的目的
why           //解释为什么需要包或模块

go mod download
用法:go mod download [-dir] [-json] [modules]。使用此命令来下载指定的模块,模块的格式可以根据主模块依赖的形式或者path@version形式指定。如果没有指定参数,此命令会将主模块下的所有依赖下载下来。
go mod download命令非常有用,主要用来预填充本地缓存或者计算Go模块代理的回答。默认情况下,下载错误会输出到标准输出,正常情况下没有任何输出。-json参数会以JSON的格式打印下载的模块对象,对应的Go对象结构是这样。

type Module struct {
  Path    string   //module path
  Version   string   //module version
  Error    string   //error loading module
  Info    string   //absolute path to cached .info file
  GoMod    string   //absolute path to cached .mod file
  Zip     string   //absolute path to cached .zip file
  Dir     string   //absolute path to cached source root directory
  Sum     string   //checksum for path, version (as in go.sum)
  GoModSum  string   //checksum for go.mod (as in go.sum)
}

go mod init
用法:go mod init [module]。此命令会在当前目录中初始化和创建一个新的go.mod文件,当然你也可以手动创建一个go.mod文件,然后包含一些module声明,这样就比较麻烦。go mod init命令可以帮助我们自动创建,例如:

go mod init example.com/m

使用这条命令时,go.mod文件必须提前不能存在。初始化会根据引入包声明来推测模块的路径或者如果你工程中之前已经存在一些依赖包管理工具,例如godepglide或者dep。那么go mod init同样也会根据依赖包管理配置文件来推断。
go mod tidy
默认情况下,Go不会移除go.mod文件中的无用依赖。所以当你的依赖中有些使用不到了,可以使用go mod tidy命令来清除它。
用法:go mod tidy [-v]它会添加缺失的模块以及移除不需要的模块。执行后会生成go.sum文件(模块下载条目)。添加参数-v,例如go mod tidy -v可以将执行的信息,即移除的模块打印到标准输出。
go mod vendor
用法:go mod vendor [-v],此命令会将build阶段需要的所有依赖包放到主模块所在的vendor目录中,并且测试所有主模块的包。同理go mod vendor -v会将添加到vendor中的模块打印到标准输出。
go mod verify
用法:go mod verify。此命令会检查当前模块的依赖是否已经存储在本地下载的源代码缓存中,以及检查自从下载下来是否有修改。如果所有的模块都没有修改,那么会打印all modules verified,否则会打印变化的内容。

虚拟版本号

go.mod文件和go命令通常使用语义版本作为描述模块版本的标准形式,这样可以比较不同版本的先后顺序。例如模块的版本是v1.2.3,那么通过重新对版本号进行标签处理,得到该版本的虚拟版本。形式如:v0.0.0-yyyymmddhhmmss-abcdefabcdef。其中时间是提交时的UTC时间,最后的后缀是提交的哈希值前缀。时间部分确保两个虚拟版本号可以进行比较,以确定两者顺序。
下面有三种形式的虚拟版本号:

  • vX.0.0-yyyymmddhhmmss-abcdefabcdef,这种情况适合用在在目标版本提交之前 ,没有更早的的版本。(这种形式本来是唯一的形式,所以一些老的go.mod文件使用这种形式)
  • vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef,这种情况被用在当目标版本提交之前的最新版本提交是vX.Y.Z-pre
  • vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef,同理,这种情况是当目标版本提交之前的最新版本是vX.Y.Z

虚拟版本的生成不需要你去手动操作,go命令会将接收的commit哈希值自动转化为虚拟版本号。

环境变量——GO111MODULE

Go 1.11中module支持临时环境变量——GO111MODULE,它可以设置以下三个值:off,on或者auto(默认)。

  1. 如果GO111MODULE=off,那么go命令行将不会使用新的module功能,相反的,它将会在vendor目录下和GOPATH目录中查找依赖包。也把这种模式叫GOPATH模式
  2. 如果GO111MODULE=on,那么go命令行就会使用modules功能,而不会访问GOPATH。也把这种模式称作module-aware模式,这种模式下,GOPATH不再在build时扮演导入的角色,但是尽管如此,它还是承担着存储下载依赖包的角色。它会将依赖包放在GOPATH/pkg/mod目录下。
  3. 如果GO111MODULE=auto,这种模式是默认的模式,也就是说在你不设置的情况下,就是auto。这种情况下,go命令行会根据当前目录来决定是否启用module功能。只有当当前目录在GOPATH/src目录之外而且当前目录包含go.mod文件或者其子目录包含go.mod文件才会启用。

具体使用步骤:

  • 首先将你的版本更新到最新的Go版本(>=1.11),如何更新版本可以自行百度。
  • 通过go命令行,进入到你当前的工程目录下,在命令行设置临时环境变量set GO111MODULE=on
  • 执行命令go mod init在当前目录下生成一个go.mod文件,执行这条命令时,当前目录不能存在go.mod文件。
  • 如果之前生成过,要先删除;如果你工程中存在一些不能确定版本的包,那么生成的go.mod文件可能就不完整,因此继续执行下面的命令;
  • 执行go mod tidy命令,它会添加缺失的模块以及移除不需要的模块
  • 执行后会生成go.sum文件(模块下载条目)。添加参数-v,例如go mod tidy -v可以将执行的信息,即删除和添加的包打印到命令行;
  • 执行命令go mod verify来检查当前模块的依赖是否全部下载下来,是否下载下来被修改过。如果所有的模块都没有被修改过,那么执行这条命令之后,会打印all modules verified
  • 执行命令go mod vendor生成vendor文件夹,该文件夹下将会放置你go.mod文件描述的依赖包,文件夹下同时还有一个文件modules.txt,它是你整个工程的所有模块。在执行这条命令之前,如果你工程之前有vendor目录,应该先进行删除。同理go mod vendor -v会将添加到vendor中的模块打印出来;

总结

到此这篇关于详解Go module的介绍及使用的文章就介绍到这了,更多相关Go module使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Django重装mysql后启动报错:No module named ‘MySQLdb’的解决方法

    发现问题 最近由于卸载Mysql时将很多相关依赖包都卸载了,重装mysql后启动django出现如下错误: django.core.exceptions.ImproperlyConfigured:Error loading MySQLdb module: No module named 'MySQLdb". Did you install mysqlclient or MySQL-python? 由于开发时python版本为3.6.4,MySQL-python不支持python3,经过一番折腾安

  • go module使用本地包的方法示例

    go module的使用非常简单 初始化go.mod go mod init 整理依赖包 go mod tidy 如果想缓存到vendor目录 go mod vendor 执行命令之后都会自动把依赖搞定. 但是, 如果我们是本地开发的包, 还没有远程仓库的时候, 要怎么解决本地包依赖问题呢? 使用replace将远程包替换为本地包服务 幸运的是, go module 提供了另外一个方案, replace, 这个replace怎么使用的呢? 我们先看一下一个最基本的mod文件 module GoR

  • 使用go module导入本地包的方法教程详解

    go module 是Go1.11版本之后官方推出的版本管理工具,并且从 Go1.13 版本开始, go module 将是Go语言默认的依赖管理工具.到今天 Go1.14 版本推出之后 Go modules 功能已经被正式推荐在生产环境下使用了. 这几天已经有很多教程讲解如何使用 go module ,以及如何使用 go module 导入gitlab私有仓库,我这里就不再啰嗦了.但是最近我发现很多小伙伴在群里问如何使用 go module 导入本地包,作为初学者大家刚开始接触package的

  • 详解Go module的介绍及使用

    Go1.1.1版本发布(2018-08-24发布)已经过去几天,从官方的博客中看到,有两个比较突出的特色,一个就是今天讲的module,模块概念.目前该功能还在试验阶段,有些地方还需要不断的进行完善.在官方正式宣布之前,打算不断修正这种支持.到时候就可以移除对GOPATH和go get命令的支持. 如果你想现在想就试试这个新功能module,需要你将你的代码仓库放到GOPATH/src目录之外.然后在那个目录下创建一个go.mod文件,从文件树中运行go命令. 主要概念介绍 module是一个相

  • es6系列教程_ Map详解以及常用api介绍

    ECMAScript 6中的Map类型是一种存储着许多键值对的有序列表.键值对支持所有的数据类型. 键 0 和 '0'会被当做两个不同的键,不会发生强制类型转换. 如何使用Map? let map = new Map(); 常用方法: set( 键,值 ): 添加新的键值对元素 get( 键 ): 获取键对应的值,如果这个值不存在,返回undefined let map = new Map(); map.set( '0', 'ghostwu' ); map.set( 0, 'ghostwu' )

  • Python自动重新加载模块详解(autoreload module)

    守护进程模式 使用python开发后台服务程序的时候,每次修改代码之后都需要重启服务才能生效比较麻烦. 看了一下Python开源的Web框架(Django.Flask等)都有自己的自动加载模块功能(autoreload.py),都是通过subprocess模式创建子进程,主进程作为守护进程,子进程中一个线程负责检测文件是否发生变化,如果发生变化则退出,主进程检查子进程的退出码(exist code)如果与约定的退出码一致,则重新启动一个子进程继续工作. 自动重新加载模块代码如下: autorel

  • Node.js API详解之 module模块用法实例分析

    本文实例讲述了Node.js API详解之 module模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 module Node.js 有一个简单的模块加载系统. 在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块). 例子,假设有一个名为 foo.js 的文件: const circle = require('./circle.js'); console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`); 在第一行中,

  • Java 类型信息详解和反射机制介绍

    RTTI RTTI(RunTime Type Information)运行时类型信息,能够在程序运行时发现和使用类型信息,把我们从只能在编译期知晓类型信息并操作的局限中解脱出来 传统的多态机制正是 RTTI 的基本使用:假设有一个基类 Shape 和它的三个子类 Circle.Square.Triangle,现在要把 Circle.Square.Triangle 对象放入 List<Shape> 中,在运行时,先把放入其中的所有对象都当作 Object 对象来处理,再自动将类型转换为 Shap

  • 详解js正则表达式语法介绍

    本文介绍了js正则表达式,具体如下: 1. 正则表达式规则 1.1 普通字符 字母.数字.汉字.下划线.以及后边章节中没有特殊定义的标点符号,都是"普通字符".表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符. 举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功:匹配到的内容是:"c":匹配到的位置是:开始于2,结束于3.(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同)

  • 详解Mybatis通用Mapper介绍与使用

    使用Mybatis的开发者,大多数都会遇到一个问题,就是要写大量的SQL在xml文件中,除了特殊的业务逻辑SQL之外,还有大量结构类似的增删改查SQL.而且,当数据库表结构改动时,对应的所有SQL以及实体类都需要更改.这工作量和效率的影响或许就是区别增删改查程序员和真正程序员的屏障.这时,通用Mapper便应运而生-- 什么是通用Mapper 通用Mapper就是为了解决单表增删改查,基于Mybatis的插件.开发人员不需要编写SQL,不需要在DAO中增加方法,只要写好实体类,就能支持相应的增删

  • 详解SpringBoot+Lucene案例介绍

    一.案例介绍 模拟一个商品的站内搜索系统(类似淘宝的站内搜索): 商品详情保存在mysql数据库的product表中,使用mybatis框架: 站内查询使用Lucene创建索引,进行全文检索: 增.删.改,商品需要对Lucene索引修改,搜索也要达到近实时的效果. 对于数据库的操作和配置就不在本文中体现,主要讲解与Lucene的整合. 二.引入lucene的依赖 向pom文件中引入依赖 <!--核心包--> <dependency> <groupId>org.apach

  • MySQL性能参数详解之Skip-External-Locking参数介绍

    MySQL的配置文件my.cnf中默认存在一行skip-external-locking的参数,即"跳过外部锁定".根据MySQL开发网站的官方解释,External-locking用于多进程条件下为MyISAM数据表进行锁定. 如果你有多台服务器使用同一个数据库目录(不建议),那么每台服务器都必须开启external locking:   参数解释 当外部锁定(external-locking)起作用时,每个进程若要访问数据表,则必须等待之前的进程完成操作并解除锁定.由于服务器访问数

  • MySQL性能参数详解之Max_connect_errors 使用介绍

    max_connect_errors是一个MySQL中与安全有关的计数器值,它负责阻止过多尝试失败的客户端以防止暴力破解密码的情况.max_connect_errors的值与性能并无太大关系. 默认情况下,my.cnf文件中可能没有此行,如果需要设置此数值,手动添加即可. 参数格式 max_connect_errors = 10 修改方法 如果系统是CentOS.Debian等,则配置文件可能位于 /etc/my.cnf .打开此文件 [root@www ~]# vi /etc/my.cnf 然

随机推荐