簡體   English   中英

同一項目中的多個模塊

[英]Multiple modules within the same project

我一直在玩 Go 模塊,我想知道以下目錄結構的最佳實踐是什么:

project
├── go.mod
├── main.go
└── players
    ├── go.mod
    ├── players.go
    └── players_test.go

一開始我在將players器 package 導入我的根項目時遇到問題,但我注意到我可以在根go.mod文件中執行此操作

module github.com/<name>/<project>

require (
    github.com/<name>/players v0.0.0
)

replace github.com/<name>/players => ./players

這讓我可以在我的main.go文件中import "github.com/<name>/players"

現在這種方法有效並取自此處,但我不確定這是否是正確的方法,或者這種方法是否僅用於在版本控制之外臨時更新本地 package。

另一種選擇,似乎有點矯枉過正,是讓每個模塊都有自己的存儲庫?

長話短說;博士; - 在同一個存儲庫中擁有多個模塊並將它們導入其他模塊/根main.go文件的最佳實踐方法是什么?

一般來說,一個模塊應該是一個包的集合。

但是您仍然可以創建單個包的模塊。 正如Volker所說,如果您希望這些包具有不同的生命周期,這可能才有意義。 當您想從另一個項目導入這些模塊並且不想要整個包集合的開銷時,這也很有意義。

一般來說:

模塊是相關 Go 包的集合,它們作為一個單元一起進行版本控制。

模塊記錄精確的依賴需求並創建可重現的構建。

大多數情況下,版本控制存儲庫只包含在存儲庫根目錄中定義的一個模塊。 (單個存儲庫中支持多個模塊,但與每個存儲庫的單個模塊相比,這通常會導致正在進行的工作更多)。

總結一下倉庫、模塊和包之間的關系:

  1. 一個存儲庫包含一個或多個 Go 模塊。 2. 每個模塊包含一個或多個 Go 包。 3. 每個包由一個或多個位於單個目錄中的 Go 源文件組成。

引用來源: https : //github.com/golang/go/wiki/Modules#modules

要回答這個問題:

你可以按照你在方法中展示的方式來做

我知道這是一個老問題,但是在一個存儲庫中管理多個模塊時,有或沒有go.work時還有一些值得一提的細節。

長話短說

每種方法都有利有弊,但如果您正在處理包含許多模塊的大型代碼庫,我建議堅持使用基於提交或標記的版本處理,並使用 Go Workspace 進行日常開發。

Go 模塊詳情

用無版本控制replace指令

當您使用指向本地目錄的replace指令時,您會發現依賴模塊的版本為v0.0.0-00010101000000-000000000000 基本上你得不到版本信息。

使用github.com/name/project模塊路徑定義的主要go.modgithub.com/name/project /name/project 模塊無法進行可重現的構建,因為replace指令的依賴目標可能已更新其內容。 如果許多模塊使用github.com/name/project/players的依賴目標,這可能會特別成問題。 這種常見的 package 的任何變化都可能同時導致所有受撫養人的行為發生變化。

如果這不是您關心的問題, replace指令應該可以正常工作。 在這樣的設置中, go.work可能是您並不真正需要的層。

有版本控制

如果您想確保版本設置適用於多個模塊的可重現和確定性構建,您可以采用幾種不同的方法。

一個go.mod ,一個存儲庫

這可能是最簡單的方法。 對於每個模塊,都有清晰的提交歷史記錄和版本控制。 只要您通過遠程存儲庫引用模塊,這可能是最簡單的設置,並且依賴設置非常清晰。

但是,請注意,這種方法意味着您需要管理多個存儲庫,而使go.work有所幫助將需要適當的本地目錄映射,這對於代碼庫的新手來說可能很困難。

基於提交的版本控制

仍然可以使用版本信息確定性地定義依賴關系,以便您可以在單個存儲庫中構建代碼。 基於提交的方法需要最少的步驟,並且仍然可以很好地工作。 不過,有一些問題需要注意。

  • 要使github.com/name/project依賴於github.com/name/project/players ,您需要確保您需要的代碼在遠程存儲庫中。 這是因為github.com/name/project將從遠程存儲庫中提取代碼和提交信息,即使存儲庫的本地副本上有相同的代碼也是如此。 這確保github.com/name/project/players的版本取自提交參考,例如v0.1.1-0.20220418015705-5f504416395d (參考: “偽版本”的詳細信息
  • 模塊名稱必須與目錄結構匹配。 例如,如果您有單個存儲庫github.com/name/project/src/mymodule/下的模塊,則模塊名稱必須為github.com/name/project/src/mymodule 這是因為當模塊路徑解析發生時, Go 找到存儲庫的根目錄(在上面的示例中,這將是github.com/name/project.git ),然后嘗試根據模塊名稱跟蹤目錄路徑。
  • 如果您在私有存儲庫中工作,則需要確保go.sum檢查不會阻止您。 您可以簡單地使用GOPRIVATE=github.com/name/project來指定您不希望跳過校驗和驗證的路徑。

基於標簽的版本控制

您可以使用 Git 標簽代替提交 SHA。

但是因為一個存儲庫中可能有很多模塊,所以 Go 模塊需要找到哪個標簽映射到哪個。 例如,具有以下目錄結構:

# All assumed to be using `github.com/name/project` prefix before package name
mypackage/          # v1.0.0
anotherpackage/     # v0.5.1
nested/dependency/  # v0.8.3

您將需要在github.com/name/project中創建標簽,命名與目錄結構完全匹配,例如:

mypackage/v1.0.0
anotherpackage/v0.5.1
nested/dependency/v0.8.3

這樣,每個標簽都被 Go 模塊正確引用,並且您的依賴關系可以保持確定性。

go.work行為

如果你有go.work在父目錄上go work use github.com/name/project/players等,優先使用本地文件。 即使您在go.mod中指定了版本,也是如此。

對於跨越多個項目的本地開發,Go Workspace 是一次處理多個項目的好方法,無需先推送依賴項的代碼更改。 但與此同時,實際發布仍然需要分解提交,以便稍后在其他代碼更改中引用第一次提交。

go.work據說是一個您很少需要提交到存儲庫的文件。 不過,您必須了解在父路徑中使用go.work會產生什么影響。

--

參考:

邊注:

我在日本舉辦的 Go 會議上就此發表了演講 - 如果您想通過示例了解更多信息,可以在這里找到一些演示代碼、幻燈片等。

在 2021/2022 年,在同一個存儲庫中擁有多個模塊並將它們導入其他模塊/根main.go文件的最佳實踐方法是 go module workspace (最早的 Go 1.18)。

請參閱“ 提案:cmd/go 中的多模塊工作區”和問題 45713

在工作目錄或包含目錄中存在go.work文件將使 go 命令進入工作區模式。
go.work文件指定了go.work成工作區的本地模塊。
在工作空間模式下調用時, go命令將始終選擇這些模塊和一組一致的依賴項。

go.work 文件:

go 1.18

directory (
    ./baz // foo.org/bar/baz
    ./tools // golang.org/x/tools
)

replace golang.org/x/net => example.com/fork/net v1.4.5

您現在擁有CL 355689

cmd/go : 添加GOWORKgo env命令

GOWORK將設置為go.work文件的路徑,如果處於工作區模式,否則將為空。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM