溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Go命令行工具項目結(jié)構(gòu)最佳實踐方法教程

發(fā)布時間:2021-10-19 16:52:13 來源:億速云 閱讀:143 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“Go命令行工具項目結(jié)構(gòu)最佳實踐方法教程”,在日常操作中,相信很多人在Go命令行工具項目結(jié)構(gòu)最佳實踐方法教程問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Go命令行工具項目結(jié)構(gòu)最佳實踐方法教程”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

用良好的package設(shè)計構(gòu)建項目

第一個最佳實踐是,項目中任何可重用的代碼都要做成一個package。如何設(shè)計package結(jié)構(gòu)和有關(guān)package的最佳時間就需要單獨寫篇文章,我做過一次關(guān)于這個內(nèi)容的分享,ppt連接在下面:

https://go-pkg-structure.dev/

把代碼放進(jìn)一個個package要比僅僅重用代碼的好處大得多。從項目結(jié)構(gòu)的角度來說,把代碼放進(jìn)獨立package有助于把一個個擁有獨立功能的代碼進(jìn)行分組,這樣更方便其他參與開發(fā)的開發(fā)者維護(hù)代碼,這對開源項目來說意義重大。

獨立成一個個package的做法能讓項目測試起來更容易。把功能獨立成一個個package,就能用更少的依賴對一個個功能進(jìn)行測試。

在創(chuàng)建和重構(gòu)項目時,我第一件事就是寫好項目需要的package,甚至?xí)趯懘a之前創(chuàng)建好基本項目結(jié)構(gòu)。

把應(yīng)用程序邏輯和接入層邏輯分開

另一個我看到用的比較多的最佳實踐是把應(yīng)用代碼和接入層代碼分離開,這里接入代碼指的是main包和main()方法。

Go和其他語言一樣,應(yīng)用的接入層代碼是main方法,當(dāng)應(yīng)用開始運行時就是最先執(zhí)行的一部分邏輯,很可能就把所有初始化邏輯都只寫在main方法里了。把各自初始化邏輯放在app包內(nèi)實現(xiàn)是比全寫在main方法里更好的做法。

把初始化邏輯放到各自package下是更好的做法,這樣也更方便做測試。比如把Start() Stop() Shutdown()方法都放到app包內(nèi),寫測試代碼時就可以在當(dāng)前包中調(diào)用啟動停止這些功能了。

下面是一個app包內(nèi)的實現(xiàn)例子:

package app  import (  "fmt"  )  var ErrShutdown = fmt.Errorf("application was shutdown gracefully")  func Start(...) error {  // Application runtime code goes here  }  func Shutdown() {  // Shutdown contexts, listeners, and such  }

如果你的命令行工具項目里,既有服務(wù)端代碼也有客戶端代碼,在一個app文件夾內(nèi)實現(xiàn)的邏輯就能被服務(wù)端和客戶端共享。

然而這個做法對簡單的命令行應(yīng)用不友好,這些應(yīng)用可能是啟動-執(zhí)行-停止的模式。但我依然選擇使用把邏輯放到app目錄下的做法,這樣可以把運行時邏輯都放在一起,降低了其他開發(fā)者對這個項目的理解難度。

main package里該放些什么?

把我們所有應(yīng)用都放到app包里之后,也要考慮main包里有什么。很簡單,main包里只有很少內(nèi)容。

總的來說,我會把main包限制為“只放與用戶交互的代碼”。例如,如果我的項目里既有cli又有服務(wù)端邏輯, 我通常會將命令行參數(shù)解析的邏輯放入main包中。服務(wù)端和客戶端cli編譯的二進(jìn)制文件會包含不同包,通過解析主程序包中的參數(shù),就可以為不同cli創(chuàng)建獨立的選項。

其他需要和用戶交互的命令行應(yīng)用,我也傾向于放進(jìn)main包,例如:

  • 命令行參數(shù)的解析

  • 用戶輸入(很簡單的輸入、不參與核心邏輯)

  • 解析配置文件

  • 退出邏輯

  • 處理信號

下面的代碼是一個main方法例子:

// main runs the command-line parsing and validations. This function will also start the application logic execution.  func main() {  // Parse command-line arguments  var opts options  args, err := flags.ParseArgs(&opts, os.Args[1:])  if err != nil {  os.Exit(1)  }  // Convert to internal config  cfg := config.New()  cfg.Verbose = opts.Verbose  // more taking command line options and putting them into a config struct.  if opts.Pass {  // ask the user for a password  }  // Run the App  err = app.Run(cfg)  if err != nil {  // do stuff  os.Exit(1)  }  }

一種推薦的項目結(jié)構(gòu)

有種被推薦了很多的一種項目結(jié)構(gòu)如下:

  • internal/app - 僅在內(nèi)部使用的核心應(yīng)用功能

  • internal/pkg/ - 僅在內(nèi)部使用的package

  • pkg/ - 需要和外部代碼進(jìn)行分享的package

  • cmd/<app_name> - 把main package放在帶有app名稱的這個目錄下

這個推薦結(jié)構(gòu)的一個重點在于把核心代碼放在internal/app、入口代碼放進(jìn)cmd/<app_name>。這種結(jié)構(gòu)對于一次編譯出好幾個二進(jìn)制文件的項目來說非常友好,比如一次編譯出server和cli的項目。cmd/<app_name>應(yīng)當(dāng)包含cli的main方法,cmd/<app_name>-server目錄下放服務(wù)端的main方法。這兩者可以在internal/app目錄下共享其他代碼。

總的來說這也是個不錯的目錄結(jié)構(gòu),但是這個目錄結(jié)構(gòu)對我不適用,看看我是怎么改的吧。

我把package放到了其他路徑下

我做的與上一段的推薦結(jié)構(gòu)不同的是package的路徑。應(yīng)用程序項目結(jié)構(gòu)的子目錄太多,這與獨立項目結(jié)構(gòu)不同,我也不喜歡用應(yīng)用程序項目結(jié)構(gòu)組織代碼。我認(rèn)為,太多子目錄阻礙開發(fā)者找到功能實現(xiàn)的代碼。

子目錄多,對代碼量很大的重量級項目來可能比較有必要,但最好不要對小型中型項目使用這種項目結(jié)構(gòu)。

我選擇把所有package都放在代碼根目錄這一層,例如我有個Parser包,它的路徑就是parser/,ssh包的路徑就是ssh/,app包路徑是app/。

這個做法使找包和功能都很容易,因為包和代碼都在項目第一層。再次強(qiáng)調(diào)下,把所有包都放在目錄第一層的做法適用于包數(shù)量不大的項目,如果項目包數(shù)量變多,那還是把包放到pkg/路徑下靠譜。

我沒有采用internal和pkg模式

我并不覺得把代碼放進(jìn)internal/或者pkg/這種實踐好,主要原因在于這種實踐是針對app內(nèi)部包。但是關(guān)于app內(nèi)部包并沒有明確的“內(nèi)”“外”劃分。對于僅在內(nèi)部使用的包,很多開發(fā)者就會因為"沒有其他人使用這些包"所以根本也沒有用最佳實踐。

我也不希望開發(fā)者在pkg路徑下像維護(hù)一個個獨立項目一樣維護(hù)代碼。實際開發(fā)中,這些包內(nèi)的接口可能和一個個獨立項目一樣做變動,那么如果這些邏輯真的是一個個分離開的,還不如放到獨立的項目里實現(xiàn)。

對我來說把我所有項目內(nèi)部代碼都放到同一個文件夾下更合理。要么是放在頂層目錄下要么是放在pkg/目錄下。

我沒有把所有文件都放進(jìn)cmd/目錄

cmd/目錄不適用于我的項目。我這個項目里有一個簡單的CLI應(yīng)用,這個應(yīng)用要方便使用者下載安裝。最快最方便的安裝辦法是使用go get命令安裝:

$ go get -u github.com/madflojo/efs2

我想要用戶只需要用go get加項目url就能安裝,但是如果用了cmd目錄就需要讓用戶在url基礎(chǔ)上增加/cmd/<app_name>才能安裝:

$ go get -u github.com/madflojo/efs2/cmd/efs2

這個url格式比較亂,用戶還需要知道我項目結(jié)構(gòu)是怎么樣的才能安裝。我希望項目結(jié)構(gòu)能讓別人更方便而不是更麻煩。所以我就把這個小應(yīng)用的main.go文件放到了項目的頂層文件夾下,這樣用戶就可以直接通過go get命令安裝應(yīng)用了,另把應(yīng)用的功能實現(xiàn)都放在app包內(nèi)。

到此,關(guān)于“Go命令行工具項目結(jié)構(gòu)最佳實踐方法教程”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

go
AI