Go 語言中常見 100 問題 - 項目結構混亂

項目結構混亂

創建一個好的 Go 項目結構並不是一件容易的事情,由於 Go 語言在設計包和模塊方面提供了很大的自由度,因此在這方面沒有通用的最佳實踐。本文將首先討論創建項目的常用組織結構,然後討論一些最佳實踐,給出改進項目組織方式的方法。

項目結構

Go 語言維護者對構建 Go 項目結構沒有嚴格的約定,在 github 上有一個稱爲標準 Go 項目結構的模板(https://github.com/golang-standards/project-layout)),注意該模板不是 Go 官方提供的。如果我們的項目很小(只有幾個文件),或者公司和項目組已經指定了項目結構規範,重新調整或遷移到上述模板格式可能不值得。如果項目還沒有結構規範,那前面這個結構值得參考借鑑。現在我們來看看這個結構模板的佈局,都有些什麼內容:

可以看到上面的標準結構中沒有 / src 目錄,這是因爲 / src 目錄太泛了,因此採用了 / cmd、/internal 和 / pkg 這種目錄。

「NOTE: 在 2021 年,Go 語言的核心維護者 Russ Cox 對上面的項目結構表達反對意見。儘管它號稱是 Go 項目標準結構,但不是官方的標準,有誤導人嫌疑。對於項目結構,沒有強制性約定必須採用上述模板。我們必須意識到這一個點,唯一注意的是項目中的各個模塊結構要保持一致,達成統一。避免在不同的結構之間發生遷移,這會浪費時間。」

包組織結構

在 Go 語言中,沒有子包的概念。但是,我們可以在子目錄中創建包。下面是標準庫 net 中的目錄結構。net 既充當包,又充當包含其他包的目錄。但是 net/http 包不繼承 net 或對 net 包具有特定的訪問權限。外界能看到 net/http 中可導出的元素。子目錄的主要好處是將包中代碼保存在具有高內聚性的地方。

/net
    /http
        client.go
        ...
    /smtp
        auth.go
        ...
    addrselect.go
    ...

對於 Go 包的組織形式,有不同的觀點。例如,我們應該按業務類型還是按層來組織應用程序,這取決於自己的喜好。我們可能傾向於按業務類型(例如客戶業務,合同業務等)對代碼進行分組,或者我們傾向於遵循六邊形原則對其進行分組。只要選擇出了適合我們的方法,保持統一即可。

對於軟件包,我們應該遵循一些最佳實踐。首先,應該避免過渡設計,因爲這可能會使得項目過於複雜。當我們搞清楚了項目包含的內容後,最好使用一個簡單的形式組織並讓項目不斷的發展,而不是強迫自己預先制定完美的結構。

包的粒度是另一個需要考慮的重要因素,我們應該避免有幾十個包含一兩個文件的小包。如果這樣設計,可能錯過了這些包之間的一些邏輯聯繫,使得項目更難讓人理解。此外,我們也應該避免使用包含很多文件的大包。總之,對於包的粒度,我們不應該走極端,導致包極小或極大。

包的命名也應該謹慎考慮。衆所周知,命名是程序開發中一件困難的事情。爲了幫助用戶理解 Go 項目,我們應該根據它提供的內容命名包,而不是它包含的內容。此外,包名要有意義。因此,包的名稱應該簡短、簡潔和富有表現力,按照慣例,應該是一個小寫單詞。

對於包導出什麼,規則非常簡單。我們應該儘可能減少應該導出的內容,以減少包之間的耦合並隱藏不必要導出的元素。如果不確定是否要導出一個元素,應該默認它不導出,在後面發現需要導出時,再調整代碼支持將其導出。我們還要注意一些特殊情況,例如,當我們對一個結構體對象調用 encoding/json 標準庫對其進行序列化或反序列化時,該結構體對象的字段需要是可導出的(即首字母要大寫),否則會忽略該字段。

組織好一個項目結構並不是一件簡單的事情,遵循上述這些規則有助於我們更容易維護。記住一點,保持結構一致對於簡化可維護非常有幫助。因此,應確保代碼庫中的代碼儘可能保持一致。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/epK_0yn_EPIWJjz9xmddcA