はじめに
Go 1.18から、マルチモジュールでの開発を便利にするためのWorkspacesモードが導入されました。今回は、Workspacesモードでどのように便利になるか紹介します。
マルチモジュール構成
比較のために、まずはWorkspacesモードではない場合のマルチモジュール構成の例を示します。
非Workspacesモードの場合
Workspacesモードではない場合の構成例は以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 | % tree . ├── items │ ├── food.go │ └── go.mod ├── main │ ├── go.mod │ └── main.go └── stores ├── go.mod └── shop.go |
それぞれ、ファイルの中身は以下のとおりです。
/items
1 2 3 | module example.com/items go 1.18 |
1 2 3 | package items const Name = "Food" |
/stores
1 2 3 | module example.com/stores go 1.18 |
1 2 3 | package stores const Name = "Shop" |
/main
1 2 3 4 5 6 7 8 9 10 11 | module example.com/main go 1.18 replace example.com/items => ../items replace example.com/stores => ../stores require example.com/items v0.0.0-00010101000000-000000000000 require example.com/stores v0.0.0-00010101000000-000000000000 |
1 2 3 4 5 6 7 8 9 10 11 12 | package main import ( "fmt" "example.com/stores" "example.com/items" ) func main() { fmt.Println(stores.Name) fmt.Println(items.Name) } |
マルチモジュール構成で開発している場合、ローカル上の他の依存モジュールを参照するためには、
go.mod
ファイルにて
replace
ディレクティブを使って参照します。この際、ローカル上の複数のモジュールに依存していると、メンテナンスが必要な
go.mod
ファイルが増えて、管理が大変になります。
Workspacesモードの場合
Workspacesモードの場合でも、ディレクトリ構成は非Workspacesモードの場合とほとんど変わりません。違いは
go.work
ファイルが有るか無いか。
1 2 3 4 5 6 7 8 9 10 11 12 13 | % tree . ├── go.work ├── items │ ├── food.go │ └── go.mod ├── main │ ├── go.mod │ └── main.go └── stores ├── go.mod └── shop.go |
また、
go.work
ファイルが有る場合、
go.mod
ファイルに
replace
ディレクティブは不要になります。
1 2 3 4 5 6 7 | go 1.18 use ( ./items // コメントを書いてもOK ./main ./stores ) |
1 2 3 4 5 6 7 | module example.com/main go 1.18 require example.com/items v0.0.0-00010101000000-000000000000 require example.com/stores v0.0.0-00010101000000-000000000000 |
ちなみに、非Workspacesモードの場合は、
main
ディレクトリの親ディレクトリから
main/main.go
を実行するとエラーになりますが、
1 2 3 4 | % go run main/main.go main/main.go:6:2: no required module provides package example.com/items: go.mod file not found in current directory or any parent directory; see 'go help modules' main/main.go:5:2: no required module provides package example.com/stores: go.mod file not found in current directory or any parent directory; see 'go help modules' |
Workspacesモードの場合は、問題なく実行できます。
1 2 3 4 | % go run main/main.go Shop Food |
go workコマンド
Workspacesモードに関する
go work
コマンドでできることを紹介します。
init
go work init [ディレクトリ]
は、
go.work
ファイルを生成します。
1 2 3 4 5 6 7 8 9 10 11 | % go work init stores items main % cat go.work go 1.18 use ( ./items ./main ./stores ) |
edit
go work edit
コマンドは
go.work
ファイルを編集するために使います。
go work edit -use [ディレクトリ名]
は、
go.work
ファイルの
use
ディレクティブに追加します。この際、実際に存在しないディレクトリでも追加されてしまうので、追加の際には注意が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 | % go work edit -use hoge % cat go.work go 1.18 use ( ./hoge ./items // hoge ./main ./stores ) |
go work edit -dropuse [ディレクトリ名]
は、
go.work
ファイルの
use
ディレクティブから削除します。
1 2 3 4 5 6 7 8 9 10 11 | % go work edit -dropuse hoge % cat go.work go 1.18 use ( ./items // hoge ./main ./stores ) |
go work edit -replace [モジュール名]=[パス]
は、今までの
replace
ディレクティブを作成できます。この際、
main/go.mod
ファイルではなく、
go.work
ファイルに追加されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 | % go work edit -replace items=../items % cat go.work go 1.18 use ( ./items // hoge ./main ./stores ) replace items => ../items |
-dropuse
と同様に、
go work edit -dropreplace [モジュール名]
は、
replace
ディレクティブを削除します。
1 2 3 4 5 6 7 8 9 10 11 | % go work edit -dropreplace items % cat go.work go 1.18 use ( ./items // hoge ./main ./stores ) |
go work edit -fmt
は、
go.work
ファイルをフォーマットしてくれますが、使用していない
module
パスを削除してくれるような事はありません。
go work edit -print
は、
go.work
ファイルを標準出力に表示します。
1 2 3 4 5 6 7 8 9 | % go work edit -print go 1.18 use ( ./items // hoge ./main ./stores ) |
go work edit -json
は、
go.work
ファイルをJSON形式で表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | % go work edit -json { "Go": "1.18", "Use": [ { "DiskPath": "./items", "ModPath": "example.com/items" }, { "DiskPath": "./main", "ModPath": "example.com/main" }, { "DiskPath": "./stores", "ModPath": "example.com/stores" } ], "Replace": null } |
sync
go work sync
は、ワークスペースのビルドリストにある依存関係を、ワークスペースの各モジュールに同期させるようです。
use
go work use [ディレクトリ]
は、
go.work
ファイルに
use
ディレクティブを追加します。この際、ディレクトリが存在する場合は
use
ディレクティブを追加し、存在しない場合はディレクトリを削除します。
また、
-r
フラグが立っている場合は、ディレクトリを再帰的に調べます。
さいごに
マルチモジュールでの開発を便利にするためのWorkspacesモードについて紹介しました。