Go の workspace の備忘録。以下は公式チュートリアル。
Tutorial: Getting started with multi-module workspaces
環境
- go 1.19.2
workspace とは
workspace とは、複数の go module を同一ディスク上で管理できる仕組みです。
A workspace is a collection of modules on disk that are used as the main modules when running minimal version selection (MVS).
A workspace can be declared in a go.work file that specifies relative paths to the module directories of each of the modules in the workspace. When no go.work file exists, the workspace consists of the single module containing the current directory.
Most go subcommands that work with modules operate on the set of modules determined by the current workspace. go mod init, go mod why, go mod edit, go mod tidy, go mod vendor, and go get always operate on a single main module.
Go Modules Reference - Workspaces
minimal version selection(MVS)
とは、Go のパッケージマネージャーである go module がパッケージの依存関係を解決するアルゴリズムのこと。Go のデフォルトでは、依存関係を満たす最少のバージョンを見つけてくる、らしいです。
Minimal Version Selection (Go & Versioning, Part 4)
ファイル構造
モノレポ環境にて、1つのリポジトリ内に複数の Go modules が管理されているとします。
. ├── go │ ├── aaa # module sample.com/sample/aaa │ │ ├── cmd │ │ │ └── main.go │ │ ├── go.mod │ │ └── go.sum │ └── bbb # module sample.com/sample/bbb │ ├── cmd │ │ └── main.go │ └── go.mod └── go.work # これが workspace の管理ファイル
workspace を利用しない場合に困る点として、IDE のプロジェクトフォルダとしてリポジトリのルートフォルダを指定すると、gopls が go.mod ファイルを見つけることができず、言語サーバーの機能が正しく動いてくれないことです。workspace を使えば解決します。
手順
初期化
リポジトリのルートフォルダで実行。
$ go work init
go.work
ファイルが作成されます。
モジュールの追加
workspace で管理したい go モジュールを追加します。go.mod ファイルのあるパスを指定。
$ go work use ./go/aaa $ go work use ./go/bbb
go.work
ファイル内に記述されます。
$ cat go.work go 1.19 use ( ./go/aaa ./go/bbb )
コードを実行してみる
go.work
ファイルのあるパスより、各モジュールに対して go コマンドを実行できます。
$ go build -o aaa ./go/aaa/cmd/main.go $ ls aaa go go.work $ $ go run go/aaa/cmd/main.go
その他設定の編集
go work edit
コマンドで、go mod
コマンドと同じようにコンフィグ編集ができる、とのこと。
go work edit
edits thego.work
file similarly togo mod edit
go.work
の replace
ディレクティブで設定された内容は、workspace で管理されている go.mod
を上書きするとのこと。
Similar to a replace directive in a go.mod file, a replace directive in a go.work file replaces the contents of a specific version of a module, or all versions of a module, with contents found elsewhere. A wildcard replace in go.work overrides a version-specific replace in a go.mod file.
replace directives in go.work files override any replaces of the same module or module version in workspace modules.
Go Modules Reference - Workspace replace
例えば、.go/util/example
に新しくモジュールを作成し、その配下にパッケージを用意しておきます。
. ├── go │ ├── aaa │ │ ├── ... │ │ └── go.sum │ ├── bbb │ │ ├── ... │ │ └── go.mod │ └── util # あたらしく作る │ └── example # あたらしく作る │ ├── ... # パッケージにあたるコードを用意 │ └── go.mod # あたらしく作る └── go.work
モジュール golang.org/x/example
の代わりにローカル上のモジュールを利用するよう、編集コマンドを実行。
$ go work edit -replace golang.org/x/example=./go/util/example $ cat go.work ... replace golang.org/x/example => ./go/util/example
この時、workspace で管理されるモジュール内で golang.org/x/example
を指定したものがある場合、./go/util/example
を利用するように上書きされます。
コマンドリファレンス。