Go 部落格

熟悉工作區

Beth Brown,Go 團隊
2022 年 4 月 5 日

Go 1.18 增加了工作區模式,讓您可以同時處理多個模組。

您可以透過訪問 下載 頁面來獲取 Go 1.18。 發行說明 包含所有更改的更多詳細資訊。

工作區

Go 1.18 中的 工作區 允許您同時處理多個模組,而無需編輯每個模組的 go.mod 檔案。工作區內的每個模組在解析依賴項時都會被視為主模組。

以前,要在其中一個模組中新增一個功能並在另一個模組中使用它,您需要釋出第一個模組的更改,或者使用 replace 指令 編輯 go.mod 檔案以引用您本地的、未釋出的模組更改。為了無誤地釋出,您必須在將本地更改釋出到第一個模組後,從依賴模組的 go.mod 檔案中刪除 replace 指令。

使用 Go 工作區,您可以透過工作區目錄根目錄中的 go.work 檔案來控制所有依賴項。go.work 檔案包含 usereplace 指令,它們會覆蓋單個 go.mod 檔案,因此無需單獨編輯每個 go.mod 檔案。

要建立工作區,請在工作區目錄列表上執行 go work init,並將模組目錄作為空格分隔的引數。工作區不需要包含您正在處理的模組。init 命令會建立一個 go.work 檔案,其中列出了工作區中的模組。如果您在沒有引數的情況下執行 go work init,該命令將建立一個空工作區。

要將模組新增到工作區,請執行 go work use [moddir] 或手動編輯 go.work 檔案。執行 go work use -r . 可以遞迴地將引數目錄中帶有 go.mod 檔案的目錄新增到您的工作區。如果一個目錄沒有 go.mod 檔案,或者不再存在,則該目錄的 use 指令將從您的 go.work 檔案中移除。

go.work 檔案的語法與 go.mod 檔案類似,幷包含以下指令:

  • go:go 工具鏈版本,例如 go 1.18
  • use:將磁碟上的模組新增到工作區中的主模組集。其引數是包含模組 go.mod 檔案的目錄的相對路徑。use 指令不會新增指定目錄子目錄中的模組。
  • replace:與 go.mod 檔案中的 replace 指令類似,go.work 檔案中的 replace 指令會將模組的 *特定版本* 或 *所有版本* 的內容替換為在其他地方找到的內容。

工作流

工作區非常靈活,支援各種工作流。以下部分將簡要概述我們認為最常見的工作流。

向外部模組新增功能並在您自己的模組中使用

  1. 為您的工作區建立一個目錄。

  2. 克隆您要編輯的外部模組。

  3. 在外部模組的本地版本中新增您的功能。

  4. 在工作區資料夾中執行 go work init [path-to-upstream-mod-dir]

  5. 修改您自己的模組,以實現新增到外部模組中的功能。

  6. 在工作區資料夾中執行 go work use [path-to-your-module]

    go work use 命令將您的模組路徑新增到您的 go.work 檔案中。

    go 1.18
    
    use (
           ./path-to-upstream-mod-dir
           ./path-to-your-module
    )
    
  7. 執行並測試您模組中使用新新增的外部模組功能。

  8. 釋出帶有新功能的外部模組。

  9. 釋出使用新功能的您的模組。

在同一儲存庫中處理多個相互依賴的模組

在同一儲存庫中處理多個模組時,go.work 檔案定義了工作區,而不是使用每個模組 go.mod 檔案中的 replace 指令。

  1. 為您的工作區建立一個目錄。

  2. 克隆包含您要編輯的模組的儲存庫。這些模組不必放在您的工作區資料夾中,因為您可以使用 use 指令指定每個模組的相對路徑。

  3. 在您的工作區目錄中執行 go work init [path-to-module-one] [path-to-module-two]

    示例:您正在處理 example.com/x/tools/groundhog,它依賴於 example.com/x/tools 模組中的其他包。

    克隆儲存庫,然後在您的工作區資料夾中執行 go work init tools tools/groundhog

    您的 go.work 檔案的內容如下所示:

    go 1.18
    
    use (
            ./tools
            ./tools/groundhog
    )
    

    tools 模組中進行的任何本地更改都將由您工作區中的 tools/groundhog 使用。

在依賴項配置之間切換

要在不同的依賴項配置下測試您的模組,您可以建立多個具有單獨 go.work 檔案的工作區,或者保留一個工作區並在單個 go.work 檔案中註釋掉您不想要的 use 指令。

建立多個工作區

  1. 為不同的依賴項需求建立單獨的目錄。
  2. 在每個工作區目錄中執行 go work init
  3. 透過 go work use [path-to-dependency] 在每個目錄中新增您想要的依賴項。
  4. 在每個工作區目錄中執行 go run [path-to-your-module],以使用其 go.work 檔案指定的依賴項。

要在同一工作區中測試不同的依賴項,請開啟 go.work 檔案並新增或註釋掉所需的依賴項。

仍在 Gopath 下工作?

也許使用工作區會改變您的想法。GOPATH 使用者可以使用位於其 GOPATH 目錄根目錄下的 go.work 檔案來解析其依賴項。工作區並非旨在完全重現所有 GOPATH 工作流,但它們可以建立一個共享 GOPATH 部分便利性,同時仍提供模組優勢的設定。

為 GOPATH 建立工作區

  1. 在您的 GOPATH 目錄的根目錄下執行 go work init
  2. 要在您的工作區中使用本地模組或特定版本作為依賴項,請執行 go work use [path-to-module]
  3. 要替換您模組 go.mod 檔案中的現有依賴項,請使用 go work replace [path-to-module]
  4. 要新增 GOPATH 或任何目錄中的所有模組,請執行 go work use -r 以遞迴地將帶有 go.mod 檔案的目錄新增到您的工作區。如果一個目錄沒有 go.mod 檔案,或者不再存在,則該目錄的 use 指令將從您的 go.work 檔案中移除。

注意:如果您有不帶 go.mod 檔案但您想新增到工作區的專案,請進入其專案目錄並執行 go mod init,然後使用 go work use [path-to-module] 將新模組新增到您的工作區。

工作區命令

除了 go work initgo work use,Go 1.18 還為工作區引入了以下命令:

  • go work sync:將 go.work 檔案中的依賴項推回到每個工作區模組的 go.mod 檔案中。
  • go work edit:提供一個命令列介面來編輯 go.work,主要供工具或指令碼使用。

模組感知構建命令和一些 go mod 子命令會檢查 GOWORK 環境變數,以確定它們是否處於工作區上下文中。

如果 GOWORK 變數指向一個以 .work 結尾的檔案路徑,則啟用工作區模式。要確定正在使用哪個 go.work 檔案,請執行 go env GOWORK。如果 go 命令不在工作區模式下,輸出將為空。

啟用工作區模式後,將解析 go.work 檔案,以確定工作區模式的三個引數:Go 版本、目錄列表和替換列表。

一些可以在工作區模式下嘗試的命令(前提是您已經知道它們的作用!)

go work init
go work sync
go work use
go list
go build
go test
go run
go vet

編輯器體驗改進

我們特別高興 Go 的語言伺服器 goplsVSCode Go 擴充套件 的升級,它們使得在 LSP 相容編輯器中處理多個模組的體驗流暢且富有成效。

在工作區內的模組之間,查詢引用、程式碼補全和跳轉到定義都可以正常工作。gopls 版本 0.8.1 引入了對 go.work 檔案的診斷、補全、格式化和懸停功能。您可以利用這些 gopls 功能與任何 LSP 相容編輯器。

編輯器特定說明

  • 最新的 vscode-go 版本 透過 Go 狀態列的快速選擇選單,可以快速訪問工作區的 go.work 檔案。

Access the go.work file via the Go status bar’s Quick Pick menu

  • GoLand 支援工作區,並計劃為 go.work 檔案新增語法高亮和程式碼補全功能。

有關在不同編輯器中使用 gopls 的更多資訊,請參閱 gopls文件

下一步是什麼?

下一篇文章: 何時使用泛型
上一篇文章: Go 如何緩解供應鏈攻擊
部落格索引