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 將建立一個作用域,並將 GOOS
和 GOARCH
設定為與檔案匹配的值。
例如,假設我們有一個包含三個模組的儲存庫:moda
、modb
和 modc
,以及一個使用模組 moda
和 modb
的 go.work
檔案。如果我們開啟檔案 moda/a.go
、modb/b.go
、moda/a_windows.go
和 modc/c.go
,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/gopls
和 golang.org/x/mod
。
cd $WORK
go work init
go work use tools/gopls mod
然後,在您的編輯器中開啟 $WORK
目錄。
何時手動配置 GOOS
、GOARCH
或 -tags
如第一節所述,gopls v0.15.0 及更高版本將在您開啟與系統預設作業系統 (GOOS
) 或架構 (GOARCH
) 不匹配的檔案時,嘗試自動配置新的構建範圍。
但是,根據該節中列出的注意事項,此自動行為存在侷限性。透過在您的 "build.env"
中設定 GOOS
或 GOARCH
,或在您的 “build.buildFlags” 中設定 -tags=...
來自定義您的 gopls 環境,當
- 您想修改預設構建環境。
- Gopls 無法猜測您希望用於跨平臺開發的
GOOS/GOARCH
組合。 - 您需要處理一個受使用者定義的構建標籤約束的檔案,例如
//go:build mytag
指令。
GOPATH 模式
當開啟 GOPATH
目錄中的目錄時,工作區範圍將僅限於該目錄及其包含的所有目錄。請注意,開啟一個大的 GOPATH 目錄可能會導致 gopls 啟動非常緩慢。
本文件的原始碼可以在 golang.org/x/tools/gopls/doc 下找到。