尊重生命,即便是螞蟻,也不會踩死。 -- JayL
如何實現企業內項目的Go Module
工程化遷移?
以本人以往所在公司的實際現狀做爲樣例,說明具體的Go Module
工程化遷移過程。html
原有Go項目均採用單一vendor
的模式進行依賴控制,即企業內全部Go項目的第三方依賴均引用該統一的vendor
倉庫,由專人專組獨立維護。這樣作的好處就是依賴包不會隨實際開發者的版本變動而變動,企業內部維護一套相對穩定的版本,缺點就是缺乏了依賴包的版本控制。git
向Go Module
工程化遷移的目標就是保持本地版本的穩定的同時兼顧版本控制功能。github
modules
倉庫在非Go Module
項目中,全部項目的依賴包,使用了vendor
倉庫,在遷移到Go Module
模式下,一樣須要相應的modules
倉庫, 來保證本地開發包依賴版本的穩定。golang
該modules
倉庫的依賴包從何而來。不妨看看:apache
$: tree -L 1 $GOPATH/pkg/mod/cache/download ├── cloud.google.com ├── git.apache.org ├── git.yixindev.net ├── github.com ├── go.opencensus.io ├── go.uber.org ├── golang.org ├── gonum.org ├── google.golang.org ├── gopkg.in ├── gotest.tools ├── honnef.co ├── k8s.io └── layeh.com
這就是咱們要維護的modules
倉庫依賴包。在開發過程當中,新的依賴包都會下載到這個路徑。將新的依賴包版本複製到modules
倉庫相應的路徑。就完成了modules
倉庫依賴包的版本維護。bash
須要注意的點是:gitlab
咱們是從$GOPATH/pkg/mod/cache/download
目錄中複製新的依賴包到modules
倉庫中。但並非全部的文件都須要進行維護,特別是本地下載過程當中的一些臨時文件。優化
$: tree -L 1 $GOPATH/pkg/mod/cache/download/github.com/x-mod/httpclient/@v/ ├── list ├── list.lock ├── v0.1.2.info ├── v0.1.2.lock ├── v0.1.2.mod ├── v0.1.2.zip ├── v0.1.2.ziphash ├── v0.2.0.info ├── v0.2.0.lock ├── v0.2.0.mod ├── v0.2.0.zip ├── v0.2.0.ziphash ├── v0.2.1.info ├── v0.2.1.lock ├── v0.2.1.mod ├── v0.2.1.zip └── v0.2.1.ziphash
在這個github.com/x-mod/httpclient
依賴包中,咱們僅僅須要具體版本的四個類型文件:google
其它類型的文件,是不須要進行modules
倉庫維護的。因此能夠在modules
倉庫中經過.gitignore
進行忽略。.net
CI
過程更新完成了modules
倉庫的維護後,咱們就能夠對原有項目的CI
過程進行更新了。在CI
編譯機或者容器上
modules
repo 到指定位置 path/to/modules
GoModule
編譯選項, 設置export GO111MODULE=on
GoProxy
環境變量, 設置經過本地文件代理: export GOPROXY=file:///path/to/modules
如今全部GO項目就會開啓GoModule
選項同時,能夠完成依賴包的版本控制。如何缺乏依賴包,只須要從本地將新增依賴包的版本添加到modules
倉庫便可。
GoGet
代理優化若是閱讀了Go Get
原理以後,針對企業依賴包的GoGet
,咱們能夠寫一個簡單的http
代理程序, 這樣就設定本身的:
// Example // code server http://aaa.com:888/user/repo.git // code import path: bbb.com/user/repo // // host => aaa.com:888 // vcs => git // root => bbb.com type Getter struct { host string //gitlab address vcs string //git root string //git } func NewGetter(host string, vcs string, root string) *Getter { return &Getter{ host: host, vcs: vcs, root: root, } } func (x *Getter) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("go-get") == "1" { sp := strings.Split(r.URL.Path[1:], "/") if len(sp) < 2 { http.Error(w, fmt.Errorf("unsupport path: %s", r.URL.Path).Error(), http.StatusBadRequest) return } prefix := fmt.Sprintf("%s/%s/%s", x.host, sp[0], sp[1]) repository := fmt.Sprintf("%s/%s/%s.%s", x.root, sp[0], sp[1], x.vcs) fmt.Fprintf(w, `<html><head><meta name="go-import" content="%s %s %s" /></head></html>`, prefix, x.vcs, repository) log.Println("go get [", prefix, "] from repository [", repository, "].") return } http.Error(w, fmt.Errorf("unsupport request: %s", r.URL.Path).Error(), http.StatusBadRequest) }
經過這個簡單的代理,你就能夠實現:
code server http://aaa.com:888/user/repo.git
code import path: bbb.com/user/repohost => aaa.com:888
vcs => git
root => bbb.com
這樣的非標依賴包的拉取了。
這一篇拖了很久,花一個小時完結掉這個系列。
更多文章可直接訪問我的BLOG:GitDiG.com