Go 部落格
組織 Go 程式碼
引言
Go 程式碼的組織方式與其他語言不同。本文討論如何為您的 Go 程式元素命名和打包,以使其更好地服務使用者。
選擇好的名稱
您選擇的名稱會影響您對程式碼的思考方式,因此在命名軟體包及其匯出的識別符號時要小心。
軟體包的名稱為其內容提供了上下文。例如,標準庫中的 bytes 軟體包匯出了 Buffer
型別。單獨來看,名稱 Buffer
並不是很具描述性,但與軟體包名稱結合後,其含義就變得清晰了:bytes.Buffer
。如果軟體包的名稱描述性較差,例如 util
,那麼緩衝區可能會獲得更長、更笨拙的名稱 util.BytesBuffer
。
在工作時不要羞於重新命名事物。隨著您花時間在程式上,您將更好地理解其各個部分如何配合,從而更好地確定它們的名稱。沒必要被早期的決定束縛住。(gofmt 命令有一個 -r
標誌,提供了語法感知的搜尋和替換功能,使大規模重構更容易。)
好的名稱是軟體介面最重要的部分:名稱是程式碼的每個客戶端首先會看到的東西。因此,精心選擇的名稱是良好文件的起點。許多以下實踐都是從好的命名自然而然產生的。
選擇好的匯入路徑(讓您的軟體包可以“go get”)
匯入路徑是使用者匯入軟體包時使用的字串。它指定了軟體包原始碼所在的目錄(相對於 $GOROOT/src/pkg
或 $GOPATH/src
)。
匯入路徑應該是全域性唯一的,因此請使用您的原始碼倉庫路徑作為其基礎。例如,來自 go.net
子倉庫的 websocket
軟體包的匯入路徑是 "golang.org/x/net/websocket"
。Go 專案擁有路徑 "github.com/golang"
,因此該路徑不能被其他作者用於不同的軟體包。因為倉庫 URL 和匯入路徑是相同的,go get
命令可以自動獲取和安裝軟體包。
如果您不使用託管的原始碼倉庫,請選擇一些唯一的、例如域名、公司或專案名稱作為字首。例如,谷歌所有內部 Go 程式碼的匯入路徑都以字串 "google"
開頭。
匯入路徑的最後一個元素通常與軟體包名稱相同。例如,匯入路徑 "net/http"
包含 http
軟體包。這不是強制要求 - 如果您願意,可以設定不同的名稱 - 但為了可預測性,您應該遵循此約定:使用者可能會驚訝於匯入 "foo/bar"
會將識別符號 quux
引入軟體包名稱空間。
有時人們會將 GOPATH
設定為他們的原始碼倉庫根目錄,並將軟體包放在相對於倉庫根目錄的子目錄中,例如 "src/my/package"
。一方面,這使得匯入路徑變短("my/package"
而不是 "github.com/me/project/my/package"
),但另一方面,這會破壞 go get
功能,並迫使使用者重新設定 GOPATH
才能使用該軟體包。請不要這樣做。
最小化匯出的介面
您的程式碼可能由許多有用的程式碼片段組成,因此很容易將大部分功能暴露在軟體包的匯出介面中。抵制這種衝動!
您提供的介面越大,您需要支援的就越多。使用者很快就會依賴您匯出的每個型別、函式、變數和常量,從而形成一個隱含的契約,您必須永久遵守它,否則可能會破壞使用者的程式。在準備 Go 1 時,我們仔細審查了標準庫的匯出介面,並刪除了我們尚未準備好承諾的部分。在分發您自己的庫時,您也應該採取類似的謹慎態度。
如果拿不準,就不要匯出!
一個軟體包中應該包含什麼
很容易將所有東西都扔進一個“大雜燴”軟體包中,但這會稀釋軟體包名稱的含義(因為它必須包含大量功能),並迫使只使用軟體包一小部分的使用者編譯和連結大量不相關的程式碼。
另一方面,也很容易過度地將程式碼拆分成小軟體包,在這種情況下,您很可能會陷入介面設計的困境,而不是把工作做完。
請參考 Go 標準庫作為指導。它的一些軟體包很大,一些很小。例如,http 軟體包包含 17 個 Go 原始檔(不包括測試)並匯出 109 個識別符號,而 hash 軟體包由一個檔案組成,只匯出三個宣告。沒有硬性規定;這兩種方法在其上下文中都是合適的。
話雖如此,main
軟體包通常比其他軟體包更大。複雜的命令包含大量在可執行檔案上下文之外幾乎沒有用處的程式碼,通常將所有程式碼儲存在一個地方更簡單。例如,go 工具超過 12000 行,分佈在 34 個檔案中。
為您的程式碼編寫文件
良好的文件是可用和可維護程式碼的基本品質。閱讀 Godoc:為 Go 程式碼編寫文件 一文,瞭解如何編寫好的文件註釋。
下一篇文章:App Engine 1.7.1 中的 Go 更新
上一篇文章:GCC 4.7.1 中的 Gccgo
部落格索引