Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Go
Code

與Go同行:Golang的命令行程序

by
Difficulty:IntermediateLength:MediumLanguages:

Chinese (Traditional) (中文(繁體)) translation by Qiang Ji (you can also view the original English article)

概述

Go語言是一種令人興奮的新語言,它能獲得了很多人氣是有一定原因的。 在本篇教程中你將學到如何用Go語言編寫命令行程序。 示例程序叫做multi-git,它允許你在同一時間對多個git存儲庫執行git命令。

Go快速介紹

Go是一個開源的類似C語言的語言,它在Google被一些C語言和Unix的駭客創建,而動機則是他們不喜歡C++語言。 這表現在Go的設計中,它做了幾個非正統的選擇,例如避開繼承的實現,模板的實現和異常的實現。 Go是簡單的,可靠的和有效的。 其最顯著的特點是通過所謂的goroutines和管道(channel)直接地支持並發編程。

在開始剖析示例程序之前,請按照官方指南為Go開發做好準備。

Multi-Git程序

Multi-git程序是一個簡單但有用的Go程序。 如果你與一隊人馬工作,代碼庫被分成多個相互聯繫的代碼存儲庫。那麼你常常需要更新代碼庫。 這裡有個問題,因為git沒有支持多個代碼庫的概念。 一切都圍繞著一個存儲庫。

如果你使用分支,這會變得特別麻煩。 如果你開發一個功能需要涉及三個存儲庫,那麼你將不得不在每個存儲庫中創建一個功能分支,然後記住同時檢出,拉,推,並合併所有這些。 這並不簡單。 Multi-git管理一組存儲庫和能夠讓你立即對整組存儲庫操作。 注意multi-git的當前版本需要你單獨地創建分支,但我可以遲點加入這個功能。

通過探索multi-git的實現方式,你將學習到很多關於編寫Go命令行程序的知識。

包和導入

Go程序是用包組織的。 multi-git程序是由一個單個的叫main.go的文件組成的。 在文件的頂部,指定包名稱“main”,然後是一個導入列表。 這些被導入的是會被multi-git程序使用到的其它包。

例如,fmt包是用來格式化I/O的,這與C語言的printf和scanf類似。 Go支持通過go get命令從各種來源安裝包。 當你安裝包時,它們以把它們安裝在$GOPATH環境變量的名稱空間下結束。 你可以經由一些通用的版本控制格式比如git, subversion, mercurial和bazaar,從各種來源比如GitHub, Bitbucket, Google code, Launchpad,甚至IBM DevOps服務來安裝包。

命令行參數

命令行參數是向程序提供輸入的最常見形式之一。 它們易於使用,允許你在一行命令中運行和配置程序,並在多種語言中都有很棒的解析支持。 Go稱它們命令行“標識”並且有指定和解析命令行參數(或標識)的標識

通常,你在程序開始時解析命令行參數,multi-git程序遵循這個約定。 進入點是main()函數。 前兩行代碼定義了兩個標識,名為“command”和“ignoreErrors”。 每個標識有一個名字,一個數據結構,一個默認值, 和一個描述字符串。 flag.Parse()的調用將解析實際的傳給程序的命令行並且定義的標識。

也可以通過flag.Args()函數訪問未定義的參數。 因此,標識代表預定義的參數,“args”是未處理的參數。 未處理的參數是基於0的索引。

環境變量

另一種程序配置的通用形式是環境變量。 當你使用環境變量時,你也許會在同樣的環境中運行相同的程序多次,所有的程序運行將使用相同的環境變量。

multi-git使用兩個環境變量:"MG_ROOT"和"MG_REPOS"。 Multi-git旨在管理一組具有公共父目錄的git存儲庫。 那就是"MG_ROOT"。 存儲庫名作為一個以逗號分隔的字符串在"MG_REPOS"環境變量中被指定。 你可以使用os.Getenv()函數讀取一個環境變量的值。

驗證存儲庫列表

現在我們有了根目錄和所有存儲庫的名字,multi-git驗證每個在根目錄下的存儲庫都存在並且的確是一個git存儲庫。 這個驗證就是簡單的看一下每個存儲庫目錄的一個.git子目錄。

首先,一個名字叫“repo”的字符串數組被定義。 然後它遍歷所有存儲庫的名字並且通過拼接根目錄和存儲庫名建立一個存儲庫路徑。 如果針對.git子目錄的[os.State()]()調用失敗,它把錯誤寫入日誌並且退出。 否則,存儲庫路徑會被加到存儲庫數組的最後。

Go有一個獨特的錯誤處理設施就是函數通常返回一個返回值和一個出錯對象。 看一下os.State()是如何返回兩個值的。 "_"佔位符被用來存儲真正的返回結果因為在這種情況下你只關心返回的錯誤。 Go是非常嚴謹的並且需要使用有名字的變量。 如果你沒有計劃去使用一個值,你應該給它賦值"_"去避免編譯錯誤。

執行Shell命令

在此刻,你有我們想執行git命令的你的存儲庫路徑的目錄。 你回想一下,我們接受一個作為單獨命令行參數(標識)叫做"command"的git命令行。 這需要被分開並存入一個組件的數組(git命令,子命令,和選項)。 完整的命令作為一個字符串也被保存以為顯示用。

現在,你對遍歷每個存儲庫並且在每個存儲庫中執行git命令都已配置好。 "for ... range"循環架構被再次使用。 首先,multi-git把它的工作目錄改變為當前目標存儲庫"r"並且打印出git命令。 然後它用exec.Command()函數執行命令並且打印出合併的輸出。

最後,它檢查在執行過程中是否有報錯。 如果有報錯並且ignoreErrors標識是假值,那麼multi-git程序安全終止。 有選擇地忽略報錯的原因是有時針對一些存儲庫的命令失敗是可以接受的。 例如,如果你想查看一個在所有存儲庫都有的名叫"cool feature"的分支,你不會在意那些沒有這個分支的存儲庫的查看失敗。

結論

Go是一個簡單但強大的語言。 它是專為大規模系統編程設計的,但對小型命令行程序也是適用的。 Go的簡樸設計與其它代語言(如Scale和Rust)形成鮮明對比,這些現代語言非常強大,設計精良,但具有非常陡峭的學習曲線。 我鼓勵你們去試試。 你會找到很多樂趣。

Envato qr branded
关注我们的公众号
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.