導讀:go modules
是 golang 1.11 新加的特性。現在 1.13 都已經發布了第 7 個小版本了,幾乎全部大項目均已開始使用,這天然也包括 Kubernetes 生態中的衆多項目。筆者在開發 OAM 相關項目的時候,卻發現 modules 的各項功能看似簡單,卻並無那麼好用,因而便想給你們分享一下使用心得,但願你們也能在最短期內學會 modules 的使用,避免踩坑。git
簡單說就是包管理,Golang 的包管理素來以混亂著稱,之前是依賴 $GOPATH
,只要你的代碼放在指定路徑下就行了,徹底沒有「包管理」的概念。被社區吐槽了好久之後開始搞vendor
機制,簡單來講就是代碼不光是能夠放到指定路徑,還能夠放在項目自身路徑的 vendor 文件夾。這個解決的問題是:你引用的代碼包上游變動不會直接影響你的項目,這顯然是開始關心「包版本」了。遺憾的是依舊沒有解決包管理的問題,好比不一樣的包依賴了同一個包的不一樣版本怎麼辦?版本間代碼衝突怎麼辦?vendor
機制並無解決,因而圍繞vendor/
社區就出了幾十個包管理工具,一時間百花齊放、百家爭鳴、各有所長,致使 golang 的包管理生態變得有些混亂。對這段歷史感興趣的能夠閱讀下筆者曾經寫的文章《Go 包管理的前世此生》。github
更有意思的是,在 go 官方社區看到包管理工具的亂象後,也作了個功能相似的工具dep
,原理與其餘各種依靠vendor/
機制的包管理工具相似,準備對包管理作統一。當你們對 dep
工具報以指望並紛紛開始切換到 dep
工具管理依賴包的時候,go 官方又發佈瞭如今的 modules 機制,徹底放棄了以前的 dep
工具與 vendor
機制。這樣的操做在社區引發了巨大的爭議,modules 與 go get
、go build
等官方工具生態有很好的集成,官方的意圖天然是但願拋開原有的歷史包袱,經過全新的方式拯救世界。然而實際體驗下來,卻依舊不盡如人意。golang
總的來講大趨勢已是用modules
,go1.13 也對 modules 機制作了很多工做。docker
言歸正傳,本文的目標是但願能用 5~10 分鐘時間帶您學會使用 go modules,而後經過 QA 的形式,描述一些常見的問題。若是但願詳細理解相關內容,也能夠參考官方文檔。api
modules 機制在 go 裏面的子命令是go mod
。緩存
modules 機制是 go 1.11 才引入的,因此開始用以前先檢查下本身的 go 版本go version
,建議使用最新的1.13 版本,涵蓋了 module 機制相關的較多更新和功能。安全
在保證 go 版本至少在 1.11 或以上以後,就要開啓一下環境變量GO111MODULE,啓用 module 機制。bash
export GO111MODULE=on
或者設置爲 auto 模式,這樣在 GOPATH 路徑下的項目能夠不使用 module 機制。網絡
export GO111MODULE=auto
建議加到 ~/.bashrc
、~/.zshrc
等配置中啓動便自動生效。運維
若是您的項目以前已經用 modules 管理了,那麼到此爲止你本地的環境已經完成初始化了。
若是項目裏以前沒有使用 modules,切換過來也很簡單,刪除原先的vendor
文件夾(保險起見能夠移動到項目以外的地方),在項目裏執行一下初始化命令便可。
go mod init [module名稱]
包名跟之前同樣,仍是跟 go path 強關聯的,好比咱們的項目通常是在http://github.com/oam-dev/oam-go-sdk
,那麼你的包名就是這個了。
go mod init github.com/oam-dev/oam-go-sdk
初始化完成後就會看見項目裏有個go.mod
文件。
而後經過 go mod download
就能夠下載全部原先 vendor
中的依賴。
使用了go module
之後,你的許多命令就會與包管理集成,好比go get
、go build
、go run
都會自動查找並在go.mod
裏面更新依賴。
因此按照 Go 官方團隊的意思,通常狀況下,你根本不用關心包管理的問題了。( 固然,這真的純粹只是官方在 YY )
因此到這裏你就已經學會go modules
了,沒超過5分鐘吧?
實際由於 go 官方對包管理重視的太晚,各類包都沒有版本的概念,隨隨便便就會出現各類衝突,並且因爲 go modules 實在是太自動了,因此就算你學會了怎麼用 modules,最後仍是會比較頭疼。
下面咱們就以 FAQ 的形式回答項目中遇到各類問題怎麼辦。
Go module 加入了代理的機制,只要設置一個代理地址,就能夠提供代理訪問。阿里雲就提供了這樣一個 go 的代理 ,是徹底免費的服務。公共代理倉庫會代理並緩存go模塊,你能夠利用該代理來避免 DNS 污染或其餘問題致使的模塊拉取緩慢或失敗的問題,加速你的項目構建。
設置的方式很是簡單,只須要設置以下環境變量便可,執行命令:
export GOPROXY=https://mirrors.aliyun.com/goproxy/
go1.13 加入了 mirror 機制,能夠經過go env -w
設置 mirror,其實就是以前的 GOPROXY 作的更到位一些,執行命令:
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
逗號後面能夠增長多個 proxy,最後的 direct 則是在全部 proxy 都找不到的時候,直接訪問,代理訪問不到的私有倉庫就能夠正常使用了。
這個功能基本上是在家遠程辦公的必備工具了。
這個幾乎是最多見的問題,比較簡單的解決方案是 hack 一下 git 配置:
git config --global url."git@gitlab.your-company.com:<your>/<package>.git".insteadOf "https://gitlab.your-company.com/<your>/<package>.git"
這個方案依賴你本地的~/.ssh/id_rsa
, 這樣你就能夠正常go get
了。
git config
,卻依賴你本地的 ~/.ssh/id_rsa
,在構建時能夠經過 multistage-build 把私鑰 add 到stage 0
裏面 build,而後用後面新的 stage 生成鏡像,這樣構建的鏡像就不會包含私鑰;go mod vendor
把包緩存下來,在 Dockerfile 構建鏡像過程當中仍是用 GOPATH 和 Vendor 機制來管理依賴。先查看版本:
$ go list -m -versions rsc.io/sampler rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99
再更新:
$ go get rsc.io/sampler@v1.3.1 go: finding rsc.io/sampler v1.3.1 go: downloading rsc.io/sampler v1.3.1 go: extracting rsc.io/sampler v1.3.1 $ go test PASS ok example.com/hello 0.022s
go 的依賴與項目名直接相關,這就致使若是咱們使用了 github 上的項目,而後項目的維護人員突發奇想改個項目名稱,就會致使全部依賴它的項目都沒法找到依賴。
還好有 replace 的機制:
replace golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
這就要梳理版本了,是最沒有捷徑的。一個比較簡單的辦法是把全部go.mod
裏不須要指定版本的包所有刪掉,僅指定必要的包版本,而後經過go build
讓項目自動構建依賴包的版本。
經過 go mod graph 能夠查看具體依賴路徑:
$ go mod graph github.com/oam-dev/oam-go-sdk github.com/go-logr/logr@v0.1.0 github.com/oam-dev/oam-go-sdk github.com/onsi/ginkgo@v1.10.1 github.com/oam-dev/oam-go-sdk github.com/onsi/gomega@v1.7.0 github.com/oam-dev/oam-go-sdk github.com/stretchr/testify@v1.4.0 github.com/oam-dev/oam-go-sdk golang.org/x/net@v0.0.0-20191004110552-13f9640d40b9 github.com/oam-dev/oam-go-sdk k8s.io/api@v0.17.0 github.com/oam-dev/oam-go-sdk k8s.io/apimachinery@v0.17.0 github.com/oam-dev/oam-go-sdk k8s.io/client-go@v0.17.0 github.com/oam-dev/oam-go-sdk sigs.k8s.io/controller-runtime@v0.4.0 ...
左邊是項目包,右邊是被依賴的包和版本。
若是確實存在兩個須要指定版本的包互相沖突,那就要作取捨,修改代碼,升級或降級某個包了。
若是在代碼調試過程當中,涉及到修改其餘依賴項目代碼,這時候就要引用本地包,也能夠採用 replace 機制:
require ( golang.org/x/crypto v0.0.0 ) replace golang.org/x/crypto v0.0.0 => ../crypto
後面這個就是個相對項目路徑的本地依賴所在路徑。
解決了上面的這些問題,基本上你就能夠愉快的使用 module 功能啦。
go mod 裏還有一些其餘功能,也在此列舉,方便你們查閱:
OAM(Open Application Model)開放應用模型是阿里聯合微軟針對雲原生應用的模型,第一次對「以應用爲中心」的基礎設施和構建規範進行了完整的闡述。應用管理者只要遵照這個規範,就能夠編寫出一個自包含、自描述的「應用定義文件」。
OAM 將應用劃分爲應用組件和應用特徵兩部分,應用組件是應用自己的邏輯,而應用特徵則是雲上的各類通用能力(如擴縮容、監控、灰度等等),大大提高了應用構建時模塊化複用能力,將雲上的各種資源和能力都轉化爲了標準化的可「聲明」對象。
同時 OAM 強調關注點分離,經過標準化的模型將應用開發不一樣階段的 API 進行分層,流程上先由研發定義應用組件,再由運維配置雲上的各類策略,最後由基礎設施團隊統一提供各種模塊化的能力。OAM 則在其中起着彼此協做的粘合劑做用,大大提升了應用交付的效率。
OAM 相關內容在 github 上徹底開源,同時咱們也爲 Go 生態編寫了oam-go-sdk方便快速實現 OAM。
目前,阿里巴巴團隊正在上游貢獻和維護這套技術,若是你們有什麼問題或者反饋,也很是歡迎與咱們在上游或者釘釘聯繫。
查看更多:https://yq.aliyun.com/article..._content=g_1000104490
上雲就看雲棲號:更多雲資訊,上雲案例,最佳實踐,產品入門,訪問:https://yqh.aliyun.com/