Go 1.18から、マルチモジュールでの開発を便利にするためのWorkspacesモードが導入されました。今回は、Workspacesモードでどのように便利になるか紹介します。
比較のために、まずはWorkspacesモードではない場合のマルチモジュール構成の例を示します。
Workspacesモードではない場合の構成例は以下のとおりです。
% tree . ├── items │ ├── food.go │ └── go.mod ├── main │ ├── go.mod │ └── main.go └── stores ├── go.mod └── shop.go
それぞれ、ファイルの中身は以下のとおりです。
/items
module example.com/items go 1.18
package items const Name = "Food"
/stores
module example.com/stores go 1.18
package stores const Name = "Shop"
/main
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
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モードの場合とほとんど変わりません。違いはgo.work
ファイルが有るか無いか。
% tree . ├── go.work ├── items │ ├── food.go │ └── go.mod ├── main │ ├── go.mod │ └── main.go └── stores ├── go.mod └── shop.go
また、go.work
ファイルが有る場合、go.mod
ファイルにreplace
ディレクティブは不要になります。
go 1.18 use ( ./items // コメントを書いてもOK ./main ./stores )
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
を実行するとエラーになりますが、
% 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モードの場合は、問題なく実行できます。
% go run main/main.go Shop Food
Workspacesモードに関するgo work
コマンドでできることを紹介します。
go work init [ディレクトリ]
は、go.work
ファイルを生成します。
% go work init stores items main % cat go.work go 1.18 use ( ./items ./main ./stores )
go work edit
コマンドはgo.work
ファイルを編集するために使います。
go work edit -use [ディレクトリ名]
は、go.work
ファイルのuse
ディレクティブに追加します。この際、実際に存在しないディレクトリでも追加されてしまうので、追加の際には注意が必要です。
% go work edit -use hoge % cat go.work go 1.18 use ( ./hoge ./items // hoge ./main ./stores )
go work edit -dropuse [ディレクトリ名]
は、go.work
ファイルのuse
ディレクティブから削除します。
% 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
ファイルに追加されます。
% 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
ディレクティブを削除します。
% 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
ファイルを標準出力に表示します。
% go work edit -print go 1.18 use ( ./items // hoge ./main ./stores )
go work edit -json
は、go.work
ファイルをJSON形式で表示します。
% 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 }
go work sync
は、ワークスペースのビルドリストにある依存関係を、ワークスペースの各モジュールに同期させるようです。
go work use [ディレクトリ]
は、go.work
ファイルにuse
ディレクティブを追加します。この際、ディレクトリが存在する場合はuse
ディレクティブを追加し、存在しない場合はディレクトリを削除します。
また、-r
フラグが立っている場合は、ディレクトリを再帰的に調べます。
マルチモジュールでの開発を便利にするためのWorkspacesモードについて紹介しました。