The Go Blog

ワークスペースに慣れる

Beth Brown、Goチーム向け
2022年4月5日

Go 1.18では、Goにワークスペースモードが追加され、複数のモジュールを同時に操作できるようになりました。

ダウンロードページからGo 1.18を入手できます。リリースノートには、すべての変更点に関する詳細が記載されています。

ワークスペース

Go 1.18のワークスペースを使用すると、各モジュールのgo.modファイルを編集することなく、複数のモジュールを同時に操作できます。ワークスペース内の各モジュールは、依存関係を解決する際にメインモジュールとして扱われます。

以前は、あるモジュールに機能を追加し、それを別のモジュールで使用するには、最初のモジュールの変更を公開するか、依存するモジュールのgo.modファイルをローカルで未公開のモジュール変更用のreplaceディレクティブで編集する必要がありました。エラーなしで公開するためには、最初のモジュールにローカルの変更を公開した後、依存するモジュールのgo.modファイルからreplaceディレクティブを削除する必要がありました。

Goワークスペースでは、ワークスペースディレクトリのルートにあるgo.workファイルを使用して、すべての依存関係を制御します。go.workファイルには、個々のgo.modファイルを上書きするuseおよびreplaceディレクティブが含まれているため、各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.modファイルでreplaceディレクティブを使用する代わりに、go.workファイルがワークスペースを定義します。

  1. ワークスペース用のディレクトリを作成します。

  2. 編集したいモジュールを含むリポジトリをクローンします。useディレクティブで各モジュールへの相対パスを指定するため、モジュールがワークスペースフォルダにある必要はありません。

  3. ワークスペースディレクトリでgo work init [path-to-module-one] [path-to-module-two]を実行します。

    例: example.com/x/toolsモジュール内の他のパッケージに依存するexample.com/x/tools/groundhogを操作しています。

    リポジトリをクローンし、ワークスペースフォルダでgo work init tools tools/groundhogを実行します。

    go.workファイルの内容は次のようになります。

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

    toolsモジュールで行われたローカルの変更は、ワークスペース内のtools/groundhogによって使用されます。

依存関係構成の切り替え

異なる依存関係構成でモジュールをテストするには、別々のgo.workファイルを持つ複数のワークスペースを作成するか、1つのワークスペースを保持し、単一の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ファイルが解析され、ワークスペースモードの3つのパラメータ(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ステータスバーのQuick Pickメニューを介してワークスペースのgo.workファイルに素早くアクセスできます。

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

  • GoLandはワークスペースをサポートしており、go.workファイルのシンタックスハイライトとコード補完を追加する予定です。

異なるエディタでgoplsを使用する方法の詳細については、goplsドキュメントを参照してください。

次は何ですか?

次の記事: ジェネリクスを使用すべき時
前の記事: Goがサプライチェーン攻撃を軽減する方法
ブログインデックス