go modules 終於不會再被GOPATH綁死了 - iT 邦幫忙

文章推薦指數: 80 %
投票人數:10人

可以使用GOProxy來解決某些地區無法使用go get的問題. 以往需要將vendor目錄一起提交到git, 避免CI/CD去拉到外部的依賴包. go modules有build cache, ... 第11屆iThome鐵人賽 DAY 12 2 SoftwareDevelopment 下班加減學點Golang與Docker系列第 12篇 gomodules終於不會再被GOPATH綁死了 11th鐵人賽 go 雷N 2019-09-1900:42:5911125瀏覽 GoModules Gomodules出現原因 解除對GOPATH的完全依賴,有gomodules就能在$GOPATH外開專案了. 不同環境或者是多專案,需要一套切換vendor目錄. 同一個依賴包的多種版本共存問題,加入了版本化的支援. 可以使用GOProxy來解決某些地區無法使用goget的問題. 以往需要將vendor目錄一起提交到git,避免CI/CD去拉到外部的依賴包. gomodules有buildcache,在CIbuildserver上速度飛快. 環境準備 Goversion>=1.11 GO111MODULE=on(GoMOdule模式),使用gomodule,不諮詢GOPATH,只是下載下來的依賴包依然存在GOPATH/pkg/mod/底下. GO111MODULE=off,這表示是GOPATH模式,查找依賴包順序如同昨天提的vendor目錄和GOPATH下. GO111MODULE=auto,默認模式,在這模式下要使用gomodule,需要滿足兩個條件 該專案目錄不在GOPATH/src/下 當前或上一層目錄存在go.mod檔案 GoMododules對於匯入依賴包的影響 可以在$GOPATH之外的地方建立專案 該專案GoModule開啟後,下載的package會放在$GOPATH/pkg/mod下. $GOPATH/bin的功能依然保持 GoModCommands 有兩種方式能定義一個正確的Gomodule //在$GOPATH/src的目錄下,建立合理的module路徑 //進入該module目錄,執行下面命令 gomodinit[modulename] /// ```bash //在任意地方,建立好module路徑 //在該目錄下,執行 gomodinit[folder/]modulename 就會在該專案下生出了go.mod文件了. go.mod的一些名詞 module 定義模組路徑 go 定義預期的goversion require 指定依賴的功能包和其版本或是更高版本[預設是最新版] exclude 排除該功能包和其版本 replace 使用不同的依賴包版本替換原有的依賴包版本 註解 //單行註解 /*多行註解*/ indirect被間接導入的依賴包 modulemy/package go1.12 requireother/thingv1.0.2//註解 requirenew/thing/v2v2.3.4//indirect excludeold/thingv1.2.3 replacebad/thingv1.4.5=>good/thingv1.4.5 同專案的子目錄 因為go.mod在專案的根目錄下,子目錄的導入路徑會是該專案的導入路徑+子目錄路徑. 舉例:建立了ithome的專案,底下有一個ironman的子目錄. 則不需要也在子目錄建立gomodinit指令,Gobuild會自動辨識ironman這目錄是ithome的一部分. GoModRequire 安裝一下logrus gogetgithub.com/sirupsen/logrus go.mod的內容 modulemodtest go1.12 requiregithub.com/sirupsen/logrusv1.4.2//indirect 此時把v1.4.2改成v1.4.1 執行 gomoddownload go.mod的內容 modulemodtest go1.12 requiregithub.com/sirupsen/logrusv1.4.1//indirect 也會發生$GOPATH/pkg/mod/github.com/sirupsen目錄下,多了[email protected]和1.4.2版本的源碼 GoModExclude go.mod的內容 modulemodtest go1.12 requiregithub.com/sirupsen/logrusv1.4.2//indirect excludegithub.com/gin-gonic/ginv1.4.0 gogetgithub.com/gin-gonic/gin 會發現應該是要下載當前最新板的v1.4.0的gin;但因為有excludegin1.4.0; 所以改成下載v1.3.9 go.mod的內容 modulemodtest go1.12 require( github.com/gin-contrib/ssev0.1.0//indirect github.com/gin-gonic/ginv1.3.0//indirect github.com/golang/protobufv1.3.2//indirect github.com/mattn/go-isattyv0.0.8//indirect github.com/sirupsen/logrusv1.4.2 github.com/ugorji/gov1.1.7//indirect gopkg.in/go-playground/validator.v8v8.18.2//indirect gopkg.in/yaml.v2v2.2.2//indirect ) excludegithub.com/gin-gonic/ginv1.4.0 如果exclude指定gin的依賴功能包,該功能包會避開該版號作安裝 GoModReplace 如果有package被replace,則編譯時會使用對應的項目來作取代. 與require類似,可以指向令一個repo 又或是指向本地的一個目錄 gomodtest //go.mod modulemodtest go1.12 requiregithub.com/sirupsen/logrusv1.4.2//indirect //modtest.go packagegomodtest import( log"github.com/sirupsen/logrus" ) funcInit(){ log.Info("godmodtestinit") } funcExec(){ log.Info("godmodtestexec") } gomaintest //go.mod modulegithub.com/tedmax100/gomaintest go1.12 replacegithub.com/tedmax100/modtest=>../gomodtest //main.go packagemain import( modtest"github.com/tedmax100/modtest" ) funcmain(){ modtest.Exec() } 執行結果 notes Replace和Exclude都只對當前這module有影響,對其他功能包不會去影響到; 其他功能包自己的replace也不會影響到這包. 自己寫個共用依賴模組用在自己的專案試試看 依賴包專案 目錄結構/GOPATH/src/ithome gomodinitgithub.com/tedmax100/ithome 因為我等等要推上github的repo中,這裡就如以前說的會有域名/目錄/專案... 這樣的層次關係. gogetgithub.com/sirupsen/logrus 這裡跟govendorfetch有些不同了,再有gomodules專案內輸入goget. 預設會去抓最新的tag版本;如果沒有設立tag,就抓最新的commit版本. go.sum這時候就會把logrus目錄下go.mod跟go.sum的依賴包跟其版本保存起來. go.sum其實跟npm的package-lock.json有著一樣的功能. go.mod(npm的package.json)定義我們指名要的依賴跟版本. go.sum把go.mod的所有依賴包,每一個像是樹的根節點一樣,開始走訪去下載,並且紀錄關係在此. ironman/ironman.go packageironman import( log"github.com/sirupsen/logrus" ) funcPrintIronMan(){ log.Info("hiironman") } ithome.go packageithome import( //這裡因為我們定義的modname就這麼長, //子目錄的導入路徑會是該專案的導入路徑+子目錄路徑. "github.com/tedmax100/ithome/ironman" log"github.com/sirupsen/logrus" ) funcPrintItHome(){ log.Info("hiItHome") ironman.PrintIronMan() } 存檔,commit,推上github. 這裡我沒有打releasetag. 可執行的專案 目錄結構/GOPATH/src/gomod gomodinitgomod //下載依賴包 goget-ugithub.com/tedmax100/ithome main.go packagemain import( "github.com/tedmax100/ithome" ) funcmain(){ ithome.PrintItHome() } 執行main.go 把依賴包給作個releasetag,試試看 //作個更新 goget-ugithub.com/tedmax100/ithome 可以看到ithome這依賴包,從本來是紀錄commithash,變成是紀錄tag版本號了. 把依賴包給再進個commit,但tag還在v0.0.1 //作個更新 goget-ugithub.com/tedmax100/ithome 正如前面說的,他會先找tag/release有沒有,沒有才去找最新的commit. 但因為我們已經有tagv0.0.1,所以怎樣更新依賴, 只要沒有更新版的依賴被release就不會被更新. 那!就來進版吧 各版本有下載過得都會在go/pkg/mod/匯入包路徑底下 反悔了!想退回去指定的某一版 gogetgithub.com/tedmax100/[email protected] 因為快取有了,就不必重抓 也會順便更改go.mod和go.sum的內容 這外部的難用,我要用自己魔改過得,放在vendor底下的 或我怕外部有人偷偷在代碼放後門,我要用自己網路cache有的,複製到vendor下 gomodvendor 這會建立出一個vendor目錄,底下有現在go.mod依賴包的代碼. 我們改一下程式 gomod/vendor/github.com/tedmax100/ithome/ithome.go packageithome import( "github.com/tedmax100/ithome/ironman" log"github.com/sirupsen/logrus" ) funcPrintItHome(){ //就改這行,存檔 log.Info("hiItHomefromvendor") ironman.PrintIronMan() } 開心的在terminal輸入 gorunmain.go 笑XD 因為只要啟用了gomodules,就會完全忽略了vendor目錄的存在,只讀取go.mod的內容. 那怎辦呢? 原本的指令gobuild,goinstall,gorunm,gotest啦 等等的加上-mod=vendor 多安裝一些依賴包 gogetgithub.com/go-sql-driver/mysql 結果最後根本沒有半個地方有import 怎辦,自己檢查每一個.go檔案,看哪些沒有import? 哪些依賴又沒有抓到呢? #addmissingandremoveunusedmodule gomodtidy 依賴包的module名稱能不能帶上版本號? 要是有breakingchange,新舊版本無法兼容呢? ithome/go.mod modulegithub.com/tedmax100/[email protected]//這裡打上版本號 go1.12 requiregithub.com/sirupsen/logrusv1.4.2 改個程式 packageithome import( "github.com/tedmax100/ithome/ironman" log"github.com/sirupsen/logrus" ) funcPrintItHome(){ log.Info("hiItHomeV0.0.7") ironman.PrintIronMan() } funcPrintItHomeV2(){ log.Info("hiItHomeV2.0") ironman.PrintIronMan() } 存檔commit,push作release 跑到執行專案,執行 goget-ugithub.com/tedmax100/ithome 這時候發現,不會去下載這2.0.0版本的依賴包 因為版本號的v2.0.0,這個第一個數字表示主版本號,不同版本間若是無法兼容使用, 則建議是提昇這版本號,且建議遠端分之多上v2分支. 版本號若是v1.10.13,這個1表示主要版本號,10表示次要版本號,13表示修正版本號 且goget-u會檢查gomod的版本號,並不會主動去下載並提昇到不同的主要版本號的依賴包. 這裡import改成使用v2版 packagemain import( "github.com/tedmax100/ithome/v2" ) funcmain(){ ithome.PrintItHome() ithome.PrintItHomeV2() } gomodtidy 開心了,收工 gomod可以相當完美的跟vendor做切換並存. 有機會來玩玩看goproxy. 留言 追蹤 檢舉 上一篇 govendor好多依賴要管理 下一篇 Defer延遲調用 系列文 下班加減學點Golang與Docker 共30篇 目錄 RSS系列文 訂閱系列文 83人訂閱 26 GogRPC第一次接觸... 27 GinWithSwagger,懶人APIDoc生成神器 28 Go鍊結參數LDFLAGS 29 Go交叉編譯與Docker<3 30 CIwithGo&DockeronGitlab 完整目錄 尚未有邦友留言 立即登入留言 iT邦幫忙鐵人賽 參賽組數 1087組 團體組數 52組 累計文章數 20470篇 完賽人數 572人 鐵人賽最新文章 gotodie?那個goto到底能不能用啊? 2021/12/12更新 予焦啦!一夢終須醒...... 盤點清查與檢測掃描-資通安全健診 [13th][Day23]httpresponseheader(下) [13th][Day22]httpresponseheader(上) [13th][Day21]golangcontext 股票怎麼選?掌握這原則,你也能找到強勢股 Gitpush 盤點清查與檢測掃描-安全性檢測 前往鐵人賽 技術推廣專區 [Day2]抓取每日收盤價 [Day1]基本工具安裝 利用python取得永豐銀行API的Nonce [Day03]tinyML開發板介紹 永豐金融API測試員 [Day01]在享受tinyML這道美食之前 [Day3]使用ta-lib製作指標 [Day4]函數打包與買進持有報酬率試算 計算API所需要的參數:HashID 計算API所需要的參數:IV 前往鐵人賽 熱門問題 公司想要客製化一套ERP系統該選擇軟體開發?套裝系統?還是自行設立部門? 軟體工程師會被監控嗎 我有一個客戶中了mljx病毒勒索950美金我免費轉讓有人要接嗎? 訂房網站DB架構 (以解決)請問GMAIL群組.假如公司之前有業務群[email protected].有新職員收不到這個.如何把新業務加入 加班提醒視窗 想找PDF編輯工具,Adobe太貴了,請問還有其他推薦的替代方案嗎? 家中的網路配置 切割vlan網段方式 【已解決】如何安裝舊版本的VS2019 IT邦幫忙 站方公告 【2021iThome鐵人賽】登登登!究竟獎落誰家,2021iThome鐵人賽得獎名單正式揭曉 熱門tag 看更多 13th鐵人賽 12th鐵人賽 11th鐵人賽 鐵人賽 2019鐵人賽 2018鐵人賽 javascript 2017鐵人賽 windows php python windowsserver linux c# 程式設計 資訊安全 css vue.js sql 分享 熱門回答 公司想要客製化一套ERP系統該選擇軟體開發?套裝系統?還是自行設立部門? 軟體工程師會被監控嗎 想找PDF編輯工具,Adobe太貴了,請問還有其他推薦的替代方案嗎? 防火牆如何設定DenyPolicy,以提高資安機制? 家中的網路配置 (以解決)請問GMAIL群組.假如公司之前有業務群[email protected].有新職員收不到這個.如何把新業務加入 RedhatEnterpriselinux5.5安裝Oracle問題 MYSQL如何將欄位中的json陣列資料拆分出來 請問目前php8版本的問題 切割vlan網段方式 熱門文章 予焦啦!一夢終須醒...... gotodie?那個goto到底能不能用啊? 盤點清查與檢測掃描-資通安全健診 再增加五隻狗勾 自己在家接收來自飛機的ADS-B訊號! 2021/12/12更新 第七隻狗勾 第九隻狗勾 第六隻狗勾 第八隻狗勾 一週點數排行 更多點數排行 海綿寶寶(antijava) ㊣浩瀚星空㊣(yoching) 居然解出來了(partyyaya) raytracy(raytracy) ccenjor(ccenjor) mathewkl(mathewkl) japhenchen(japhenchen) 純真的人(jer5173) 小山丘(a243318490) fillano(fillano) × At 輸入對方的帳號或暱稱 Loading 找不到結果。

標記 {{result.label}} {{result.account}} 關閉



請為這篇文章評分?