Gopls: ワークスペースの設定
言語サーバープロトコルでは、「ワークスペース」はフォルダーとフォルダーごとの設定で構成されます。VS Codeなどの一部のLSPクライアントはワークスペースを明示的に設定できますが、他のクライアントはワークスペースルートを定義する特別なファイル(例: .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 の3つのモジュールを持つリポジトリと、moda と modb のモジュールを使用する go.work ファイルがあるとします。もし moda/a.go、modb/b.go、moda/a_windows.go、modc/c.go のファイルを開いた場合、goplsは自動的に3つのビルドを作成します。

これにより、Goファイルを開いたときにgoplsが単に機能するようになりますが、いくつかの注意点があります。
- これは、goplsが1つではなく3つのビルドを追跡するため、より多くの作業を行うことになります。しかし、最近のスケーラビリティ再設計により、効率的なキャッシュによってこの作業の多くを回避できます。
- 特定のファイルから呼び出される操作(例:「参照」や「実装」)の場合、goplsはそのファイルに対するデフォルトのビルドで操作を実行します。例えば、
foo_linux.goからシンボルSの参照を検索するとLinuxビルドからの参照が返され、foo_windows.goから同じシンボルSの参照を検索するとWindowsビルドからの参照が返されます。Goplsはファイルのデフォルトビルドを検索しますが、他の可能なすべてのビルドを検索することはありません(それは素晴らしいことですが、費用がかかりすぎるため)。イシュー#65757と#65755はこの動作の改善を提案しています。 - ビルド制約付きファイルと一致する
GOOS/GOARCHの組み合わせを選択する際、goplsはこのリストから最初の一致する組み合わせを選択します。場合によっては、これは驚くべきことです。 - デフォルトのツールチェーンと一致しない
GOOS/GOARCH制約付きファイルで作業している場合、ターゲットのCツールチェーンが利用できる可能性が低いため、CGO_ENABLED=0が暗黙的に設定されます。これは、import "C"を含むファイルではgoplsが機能しないことを意味します。イシュー#65758はこの動作の改善につながる可能性があります。 - Goplsは現在、ビルドディレクティブ
//go:build mytagのような任意のユーザー定義ビルド制約を含むビルドフラグを推測できません。イシュー#65089は、goplsがこれを自動的に処理できるヒューリスティックを提案しています。
この動作についてフィードバックをいただければ幸いです。上記で言及されたイシューに賛成票を投じるかコメントするか、または他に希望する改善点については新しいイシューを開いてください。
開発で go.work ファイルを使用するタイミング
Go 1.18以降、go コマンドはgo.work ファイルで指定されるマルチモジュールワークスペースを内蔵でサポートしています。Goplsは、これらのファイルがワークスペースに存在する場合、それらを認識します。
次のような場合に go.work ファイルを使用します。
- 単一の論理ビルドで複数のモジュールを同時に作業したい場合。例えば、あるモジュールへの変更を別のモジュールに反映させたい場合など。
- 追跡する必要があるビルドの数を減らすことで、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 の下にあります。