那一天我二十一歲,在我一辈子的黃金時代,我有好多奢望。我想愛,想吃,還想在一瞬間變整天上半明半暗的雲,後來我才知道,生活就是個緩慢受錘的過程,人一每天老下去,奢望也一每天消逝,最後變得像挨了錘的牛一樣。但是我過二十一歲生日時沒有預見到這一點。我覺得本身會永遠生猛下去,什麼也錘不了我。 -- 王小波 《黃金時代》
接上篇: Go Module 工程化实践(一):基础概念篇。git
go get
取包原理篇不管是否开启Go Module
功能,go get
从版本控制系统VCS
中取包的基础过程是相似的,除了在新的实现中再也不循环拉取submodule
子模块之外。github
go get
基础取包流程假设依赖包github.com/liujianping/foo
不在本地,须要经过go get
获取。发起如下命令:golang
$: go get github.com/liujianping/foo
命令发出后:正则表达式
go get
能够指定具体包的import
路径或者经过其自行分析代码中的import
得出须要获取包的路径。可是import
路径,并不直接就是该包的查询路径。在go get
的源码实现中,包的查询路径是经过一组正则匹配出来的。也就是说,import
路径是必须匹配这组正则表达式的,若是不匹配的话,代码是确定没法编译的。笔者就贴一下这组正则表达式中的github正则与私有仓库的正则:segmentfault
// Github { prefix: "github.com/", re: `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`, vcs: "git", repo: "https://{root}", check: noVCSSuffix, }, //省略其它VCS... // General syntax for any server. // Must be last.私有仓库将会使用该正则 { re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`, ping: true, },
以包路径github.com/liujianping/foo
为例,正则匹配后,得出的查询路径就是:ssh
https://github.com/liujianping/foo
curl
再结合go-get
参数,向远端VCS系统发起https://github.com/liujianping/foo?go-get=1
请求。svn
包的远端仓库地址,能够经过go get
请求的响应中的go-import
的meta标签中的content中获取的。gitlab
$: curl https://github.com/liujianping/foo?go-get=1 | grep go-import <meta name="go-import" content="github.com/liujianping/foo git https://github.com/liujianping/foo.git">
例子中的包对应的远端仓库地址就是:https://github.com/liujianping/foo.git
.测试
clone
到本地虽然版本控制系统VCS
自己就存在各种区别,可是一些基础操做大多相似。在go get
中具体clone
的过程会根据具体的VCS
采用对应的操做。
go get
代理取包流程了解了go get
取包的基础流程后,说说Go Module
功能开启后的完整流程。
开启Go Module
后,go get
增长了一个新的环境变量GOPROXY
。该环境变量一旦开启,go get
就彻底切换到新的取包流程,即GOPROXY
流程,暂时就这么称呼吧。
在GOPROXY
流程中,官方定义了一组代理接口, 请参考官方接口定义。
GET $GOPROXY/<module>/@v/list returns a list of all known versions of the given module, one per line.GET $GOPROXY/<module>/@v/<version>.info returns JSON-formatted metadata about that version of the given module.
GET $GOPROXY/<module>/@v/<version>.mod returns the go.mod file for that version of the given module.
GET $GOPROXY/<module>/@v/<version>.zip returns the zip archive for that version of the given module.
其实这组接口的定义就是$GOPATH/pkg/mod/cache/download
中的文件系统。就是说,咱们能够直接将此目录下的文件系统做为代理使用,以下命令:export GOPROXY=file:///$GOPATH/pkg/mod/cache/download/
关于GOPROXY
代理服务,网上有不少实现,官方也推荐了几个。各有各的问题,只能这样说。由于,对于一些定制话的需求,例如:
尚无完美的解决方案。可是即便这样,咱们仍是能够根据具体的工程化需求构建企业内部的一套标准的GO Module
流程来。具体方案,在下一篇工程实践篇中讲解。
私有仓库的取包过程当中出现的问题大多集中在基础取包过程当中。具体的异常又可能发生在2.1.1~2.1.3任一阶段。分别列举常见问题与解决思路。
clone
阶段的权限问题一般状况下,私有仓库的访问是基于帐号权限的。例如,private.vcs.com/group/foo
的包路径,在go get
过程当中,会正则匹配出https://private.vcs.com/group/foo.git
的仓库路径,假设VCS系统是gitlab搭建的。
那么在git clone https://private.vcs.com/group/foo.git
的过程当中,系统会提醒用户提供用户名与登陆密码。每次输入就会很累赘。
解决方案有二:
增长$HOME/.gitconfig
配置:[url "ssh://git@github.com/MYORGANIZATION/"]
insteadOf = https://github.com/MYORGANIZA...
将原有的https访问方式替换成ssh方式。
增长$HOME/.netrc
:machine github.com login YOU password APIKEY
将其中的 APIKEY 换成本身的登陆KEY。
虽然采用的github为例,但适用于gitlab服务。其实,还有一种解决方案,该方案,还能解决2.3.2中的问题,故在下节中讲解。
因为历史缘由,笔者公司的gitlab服务地址就是非标准的路径,标准路径应该是: https://private.vcs.com
,而笔者公司的gitlab路径则是: https://private.vcs.com:888
.
若是按go get
流程,import包路径应该采用d:private.vcs.com:888/group/foo
,就能够正确匹配出该仓库的合理地址了。可是很不幸,在实际操做中,失败了结。具体缘由读者能够自行测试一下。
此时惟一的办法,就是搭建一个中间服务:https://private.vcs.com
可以经过go get
的包路径匹配查询正确的仓库地址。
更多文章可直接访问我的BLOG:GitDiG.com