こんにちは。よっしーです(^^)
今日は、GolangのWorkspacesについてご紹介します。
概要
本記事では、Golangの multi-module workspaces の基本をご紹介します。multi-module workspaces を使うと、Goコマンドに複数のモジュールで同時にコードを書いていることを伝え、それらのモジュールでコードを簡単にビルドして実行することができます。
共有の multi-module workspaces に2つのモジュールを作成し、それらのモジュールに渡って変更を加え、ビルドでその結果を確認していきます。
Workspacesの機能を利用するには、Go 1.18以降が必要になります。
利用手順
モジュール作成
最初に作業ディレクトリを作成します。手順は下記のコマンドになります。
mkdir 12_learn-golang-workspaces
cd 12_learn-golang-workspaces
asdfコマンドで使用するGolangのバージョンを指定します。すでにGolangが実行できる状態にある方は、このコマンドをスキップしても問題ありませんが、Go 1.18以降である必要があります。
asdf local golang 1.20.5
モジュールの初期化を初期化します。この例では、golang.org/x/exampleモジュールに依存する新しいhelloモジュールを作成します。
mkdir hello
cd hello
go mod init example.com/hello
golang.org/x/example モジュールの依存関係を go get で追加します。
go get golang.org/x/example
helloディレクトリに以下の内容でhello.goを作成します。
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("Hello"))
}
helloプログラムを実行します。
go run example.com/hello
下記のような出力になっていれば成功です。
% go run example.com/hello
olleH
Workspaces作成
次にWorkspacesの作成をします。モジュールでWorkspacesを指定するためにgo.workファイルを作成します。
cd 12_learn-golang-workspaces
go work init ./hello
go work initコマンドは、./helloディレクトリのモジュールを含むワークスペースのgo.workファイルを作成するようgoに指示します。
goコマンドは、次のようなgo.workファイルを作成します。
go 1.20
use ./hello
go.workファイルは、go.modと同様の構文です。
goディレクティブは、そのファイルがどのバージョンのGoで解釈されるべきかをGoに指示します。これはgo.modファイルのgoディレクティブと似ています。
useディレクティブは、ビルド時にhelloディレクトリのモジュールをメインモジュールにするようGoに指示します。
そのため、workspaceのどのサブディレクトリでも、このモジュールが有効になります。
workspaceディレクトリでプログラムを実行すると、helloディレクトリで実行したのと同じ結果になります。
% go run example.com/hello
olleH
Goコマンドは、ワークスペースにあるすべてのモジュールをメインモジュールとして含めます。これにより、モジュールの外でも、モジュール内のパッケージを参照することができます。モジュールやワークスペースの外でgo runコマンドを実行すると、goコマンドはどのモジュールを使えばいいのかわからず、エラーになります。
golang.org/x/exampleモジュールをワークスペースに追加
そして、golang.org/x/exampleモジュールのローカルコピーをワークスペースに追加します。また、Reverse の代わりに使える新しい関数を stringutil パッケージに追加します。
まず、golang.org/x/example モジュールを含む Git リポジトリのコピーをダウンロードし、ワークスペースに追加し、hello プログラムから使用する新しい関数をそのモジュールに追加します。
ワークスペース・ディレクトリから、gitコマンドを実行して、リポジトリをクローンします。
git clone https://go.googlesource.com/example
ワークスペースにモジュールを追加します。
go work use ./example
go work use コマンドは、go.work ファイルに新しいモジュールを追加します。これで、次のようになります。
go 1.20
use (
./example
./hello
)
example.com/helloモジュールとgolang.org/x/exampleモジュールの両方が含まれるようになりました。
これにより、go getコマンドでダウンロードしたモジュールキャッシュ内のモジュールのバージョンの代わりに、stringutilモジュールのコピーに書く新しいコードを使うことができるようになります。
文字列を大文字にする新しい関数を golang.org/x/example/stringutil パッケージに追加してみます。
example/stringutilディレクトリに、以下の内容を含むtoupper.goというファイルを新規に作成します。
touch example/stringutil/toupper.go
package stringutil
import "unicode"
// ToUpper uppercases all the runes in its argument string.
func ToUpper(s string) string {
r := []rune(s)
for i := range r {
r[i] = unicode.ToUpper(r[i])
}
return string(r)
}
ToUpper関数を使用するようにhelloプログラムを以下の内容に修正します。
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.ToUpper("Hello"))
}
ワークスペース・ディレクトリから、以下を実行します。
% go run example.com/hello
HELLO
Goコマンドは、コマンドラインで指定されたexample.com/helloモジュールをgo.workファイルで指定されたhelloディレクトリに見つけ、同様にgolang.org/x/exampleのインポートをgo.workファイルを用いて解決します。
go.workはreplaceディレクティブを追加する代わりに、複数のモジュールにまたがって作業するために使うことができます。
2つのモジュールは同じワークスペースにあるので、あるモジュールで変更を加え、それを別のモジュールで使用することは簡単です。
解説
workspacesについて
ワークスペースとは、ディスク上のモジュールの集まりで、実行する際のメインモジュールのバージョンはMinimal Version Selection(MVS)により決定されます。
ワークスペースは、ワークスペース内の各モジュールのモジュール・ディレクトリへの相対パスを指定した go.work ファイルで宣言することができます。go.workファイルが存在しない場合、ワークスペースはカレントディレクトリを含む単一のモジュールで構成される。
モジュールを扱うほとんどのgoサブコマンドは、現在のワークスペースによって決定されたモジュールのセットに対して動作します。go mod init、go mod why、go mod edit、go mod tidy、go mod vendor、およびgo getは常に単一のメインモジュールに対して動作します。
コマンドは、まず環境変数GOWORKを調べることによって、それがワークスペース・コンテキストにあるかどうかを判断する。GOWORKがoffに設定されている場合、コマンドは単一モジュール・コンテキストの中にあることになります。環境変数GOWORKが空であるか、または提供されていない場合、コマンドは現在の作業ディレクトリを検索し、次に連続する親ディレクトリを検索して、ファイルgo.workを探します。ファイルが見つかった場合、コマンドはそれが定義するワークスペースで動作します。そうでない場合、ワークスペースは作業ディレクトリを含むモジュールのみを含みます。GOWORKが.workで終わる既存のファイルへのパスを指定した場合、ワークスペース・モードが有効になります。それ以外の値はエラーとなります。go env GOWORKコマンドは、goコマンドがどのgo.workファイルを使用しているかを判断するために使用できます。go env GOWORKは、goコマンドがワークスペースモードでない場合は空です。
今回は、ワークスペースを利用しているので下記のような出力になります。
% go env GOWORK
/Users/xxx/github/Musica/12_learn-golang-workspaces/go.work
おわりに
今日は、GolangのWorkspacesについてご紹介しました。
本記事で使用したコードは下記のリポジトリにあります。
何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント