Gopls:設定您的工作區

在語言伺服器協議中,“工作區”由一個資料夾以及每個資料夾的配置組成。一些 LSP 客戶端(如 VS Code)允許顯式配置工作區,而另一些客戶端則透過查詢定義工作區根目錄的特殊檔案(例如 .git 目錄或 go.mod 檔案)來自動進行配置。

為了正常工作,gopls 需要一個定義好的範圍,在該範圍內應執行諸如引用、重新命名和實現等語言功能。換句話說,gopls 需要從 LSP 工作區推斷出您將用於構建工作區的 go build 呼叫,包括工作目錄、環境和構建標誌。

過去,設定工作區以使 gopls 推斷出正確的構建資訊可能很棘手。這需要開啟正確的目錄或使用 go.work 檔案告知 gopls 您正在處理的模組,並提前配置正確的作業系統和架構。當這未能如預期工作時,gopls 經常會以神秘的方式失敗——可怕的“未找到包”錯誤。

從 gopls v0.15.0 開始,工作區配置變得更加簡單,當您在工作區中的任何位置開啟 Go 檔案時,gopls 通常都可以正常工作。如果它對您不起作用,或者您想更好地瞭解 gopls 如何建模您的工作區,請繼續閱讀。

工作區構建

從 gopls v0.15.0 開始,gopls 將根據開啟的檔案集猜測您正在處理的構建。當您在工作區資料夾中開啟一個檔案時,gopls 會檢查該檔案是否包含在模組、go.work 工作區或 GOPATH 目錄中,並相應地配置構建。此外,如果您開啟一個受限於不同作業系統或架構的檔案(例如,在 Linux 上工作時開啟 foo_windows.go),gopls 將建立一個作用域,並將 GOOSGOARCH 設定為與檔案匹配的值。

例如,假設我們有一個包含三個模組的儲存庫:modamodbmodc,以及一個使用模組 modamodbgo.work 檔案。如果我們開啟檔案 moda/a.gomodb/b.gomoda/a_windows.gomodc/c.go,gopls 將自動建立三個構建。

Zero Config gopls

這使得 gopls 在您開啟 Go 檔案時能夠“即插即用”,但這也帶來了一些需要注意的事項:

  • 這會導致 gopls 進行更多工作,因為它現在需要跟蹤三個構建而不是一個。但是,最近的 可伸縮性重新設計 透過高效的快取可以避免其中的許多工作。
  • 對於從給定檔案呼叫的操作,例如“引用”或“實現”,gopls 會在該檔案的預設構建中執行該操作。例如,從 foo_linux.go 查詢符號 S 的引用將返回來自 Linux 構建的引用,而從 foo_windows.go 查詢同一符號 S 的引用將返回來自 Windows 構建的引用。Gopls 會搜尋該檔案的預設構建,但不會搜尋所有其他可能的構建(儘管那樣會很好),因為這可能會非常耗時。問題 #65757#65755 提出了對此行為的改進。
  • 在選擇 GOOS/GOARCH 組合以匹配受構建約束的檔案時,gopls 將從 此列表 中選擇第一個匹配的組合。在某些情況下,這可能會令人驚訝。
  • 當在與您的預設工具鏈不匹配的 GOOS/GOARCH 受約束的檔案中工作時,將隱式設定 CGO_ENABLED=0,因為不太可能為該目標提供 C 工具鏈。這意味著 gopls 將無法處理包含 import "C" 的檔案。問題 #65758 可能會對此行為進行改進。
  • Gopls 目前無法猜測包含任意使用者定義構建約束的構建標誌,例如帶有 //go:build mytag 指令的檔案。問題 #65089 提出了一個 gopls 可以自動處理此問題的啟發式方法。

請透過點贊或評論上述問題,或就您希望看到的其他改進 提出新問題 來提供關於此行為的反饋。

何時使用 go.work 檔案進行開發

從 Go 1.18 開始,go 命令內建支援由 go.work 檔案指定的多個模組的工作區。如果 go.work 檔案存在於您的工作區中,Gopls 將會識別它們。

當您需要以下情況時,請使用 go.work 檔案:

  • 您想在單個邏輯構建中同時處理多個模組,例如,您希望一個模組的更改反映在另一個模組中。
  • 您想透過減少 gopls 必須跟蹤的構建數量來提高 gopls 的記憶體使用量或效能。
  • 您希望 gopls 在多模組工作區中知道您正在處理哪些模組,而無需開啟任何檔案。例如,在開啟任何檔案之前使用 workspace/symbol 查詢可能很方便。
  • 您正在使用 gopls v0.14.2 或更早版本,並且想處理多個模組。

例如,假設此儲存庫已檢出到 $WORK/tools 目錄,而 x/mod 已檢出到 $WORK/mod,並且您正在處理一個用於編輯 go.mod 檔案的新 x/mod API,您想同時將其整合到 gopls 中。

您可以透過建立 go.work 檔案來同時處理 golang.org/x/tools/goplsgolang.org/x/mod

cd $WORK
go work init
go work use tools/gopls mod

然後,在您的編輯器中開啟 $WORK 目錄。

何時手動配置 GOOSGOARCH-tags

如第一節所述,gopls v0.15.0 及更高版本將在您開啟與系統預設作業系統 (GOOS) 或架構 (GOARCH) 不匹配的檔案時,嘗試自動配置新的構建範圍。

但是,根據該節中列出的注意事項,此自動行為存在侷限性。透過在您的 "build.env" 中設定 GOOSGOARCH,或在您的 “build.buildFlags” 中設定 -tags=... 來自定義您的 gopls 環境,當

  • 您想修改預設構建環境。
  • Gopls 無法猜測您希望用於跨平臺開發的 GOOS/GOARCH 組合。
  • 您需要處理一個受使用者定義的構建標籤約束的檔案,例如 //go:build mytag 指令。

GOPATH 模式

當開啟 GOPATH 目錄中的目錄時,工作區範圍將僅限於該目錄及其包含的所有目錄。請注意,開啟一個大的 GOPATH 目錄可能會導致 gopls 啟動非常緩慢。


本文件的原始碼可以在 golang.org/x/tools/gopls/doc 下找到。