Go 部落格

熟悉工作區

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

Go 1.18 將工作區模式新增至 Go,讓您能同時套用多個模組。

您可以拜訪 下載 頁面取得 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 檔案,或不再存在,則會從 go.work 檔案中移除該目錄的 use 指令。

注意:如果你有想加入工作區的專案,但沒有 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 相容編輯器工作中使用多個模組變成一種順暢且有回報的體驗。

在工作空間內的模組中,尋找參考、程式碼完成和轉到定義都能運作。gopls0.8.1 版本加入了 go.work 檔案的診斷、完成、格式化和提示。你可以透過任何與 LSP 相容的編輯器 來利用這些 gopls 功能。

編輯器特定注意事項

  • 最新的 vscode-go 發行版本 可透過「Go」狀態列 Quick Pick 選單快速存取工作區中的 `go.work` 檔案。

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

  • GoLand 支援工作區,並計畫新增 `go.work` 檔案的語法突顯和程式碼補完功能。

如需進一步了解如何在各種編輯器中使用 `gopls`,請參閱 `gopls` 文件

接下來要怎樣做?

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