The Go Blog (Go ブログ)

ワークスペースに慣れる

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 [アップストリームモジュールディレクトリへのパス] を実行します。

  5. アップストリームモジュールに追加された機能を実装するために、独自のモジュールを変更します。

  6. ワークスペースフォルダーで go work use [モジュールへのパス] を実行します。

    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 [モジュール1へのパス] [モジュール2へのパス]` を実行します。

    例: `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 [依存関係へのパス]` を使用して、各ディレクトリ内に必要な依存関係を追加します。
  4. 各ワークスペースディレクトリで `go run [モジュールへのパス]` を実行して、その `go.work` ファイルで指定された依存関係を使用します。

同じワークスペース内で異なる依存関係をテストするには、`go.work` ファイルを開き、目的の依存関係を追加またはコメントアウトします。

まだ GOPATH を使用していますか?

おそらくワークスペースを使用することで気が変わるでしょう。`GOPATH` ユーザーは、`GOPATH` ディレクトリのベースにある `go.work` ファイルを使用して依存関係を解決できます。ワークスペースはすべての `GOPATH` ワークフローを完全に再現することを目的としていませんが、モジュールの利点を提供しながら `GOPATH` の利便性の一部を共有するセットアップを作成できます。

GOPATH のワークスペースを作成するには

  1. `GOPATH` ディレクトリのルートで `go work init` を実行します.
  2. ローカルモジュールまたは特定のバージョンをワークスペースの依存関係として使用するには、`go work use [モジュールへのパス]` を実行します。
  3. モジュールの `go.mod` ファイルの既存の依存関係を置き換えるには、`go work replace [モジュールへのパス]` を使用します。
  4. GOPATH または任意のディレクトリにあるすべてのモジュールを追加するには、`go work use -r` を実行して、`go.mod` ファイルを持つディレクトリをワークスペースに再帰的に追加します。ディレクトリに `go.mod` ファイルがない場合、またはディレクトリが存在しない場合、そのディレクトリの `use` ディレクティブは `go.work` ファイルから削除されます。

注: ワークスペースに追加したい `go.mod` ファイルのないプロジェクトがある場合は、プロジェクトディレクトリに移動して `go mod init` を実行し、`go work use [モジュールへのパス]` を使用して新しいモジュールをワークスペースに追加します。

ワークスペースコマンド

`go work init` と `go 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 ステータスバーのクイックピックメニューからワークスペースの go.work ファイルにすばやくアクセスできます。

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

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

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

次のステップ

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