go-get速度慢完美解决

https://mirrors.aliyun.com/go...https://goproxy.io/zh/以上。

August 28, 2019 · 1 min · jiezi

Go Module 工程化实践(二):go get 取包原理篇

接上篇: Go Module 工程化实践(一):基础概念篇。2. go get 取包原理篇不论是否开启Go Module功能,go get从版本控制系统VCS中取包的基础过程是类似的,除了在新的实现中不再循环拉取submodule子模块以外。2.1 go get 基础取包流程假设依赖包github.com/liujianping/foo不在本地,需要通过go get获取。发起以下命令:$: go get github.com/liujianping/foo命令发出后:2.1.1 第一步,正则匹配出依赖包的查询路径go get可以指定具体包的import路径或者通过其自行分析代码中的import得出需要获取包的路径。但是import路径,并不直接就是该包的查询路径。在go get的源码实现中,包的查询路径是通过一组正则匹配出来的。也就是说,import路径是必须匹配这组正则表达式的,如果不匹配的话,代码是肯定无法编译的。笔者就贴一下这组正则表达式中的github正则与私有仓库的正则: // Github { prefix: “github.com/”, re: ^(?P&lt;root&gt;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&lt;root&gt;(?P&lt;repo&gt;([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P&lt;vcs&gt;bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$, ping: true, },以包路径github.com/liujianping/foo为例,正则匹配后,得出的查询路径就是:https://github.com/liujianping/foo再结合go-get参数,向远端VCS系统发起https://github.com/liujianping/foo?go-get=1请求。2.1.2 第二步,查询得出包的远端仓库地址包的远端仓库地址,可以通过go get请求的响应中的go-import的meta标签中的content中获取的。$: 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.2.1.3 第三步,根据仓库地址clone到本地虽然版本控制系统VCS本身就存在各类区别,但是一些基础操作大多类似。在go get中具体clone的过程会根据具体的VCS采用对应的操作。2.2 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代理服务,网上有很多实现,官方也推荐了几个。各有各的问题,只能这样说。因为,对于一些定制话的需求,例如:私有仓库的权限问题个别库的镜像国内无法访问等完美的解决方案,暂时还没有。但是即使这样,我们还是可以根据具体的工程化需求构建企业内部的一套标准的流程来。具体方案,在下一篇工程实践篇中讲解。2.3 私有仓库取包过程中的常见问题私有仓库的取包过程中出现的问题大多集中在基础取包过程中。具体的异常又可能发生在2.1.1~2.1.3任一阶段。分别列举常见问题与解决思路。2.3.1 私有仓库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中的问题,故在下节中讲解。2.3.2 私有VCS非标路径问题由于历史原因,笔者公司的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的包路径匹配查询正确的仓库地址。其实该中间服务器的实现就非常简单。具体实现,笔者留到下一偏:工程实践篇 讲解。 ...

March 7, 2019 · 1 min · jiezi