Go言語入門:workspaces の使い方

スポンサーリンク
Go言語入門:workspaces の使い方 ノウハウ
Go言語入門:workspaces の使い方
この記事は約8分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、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についてご紹介しました。

本記事で使用したコードは下記のリポジトリにあります。

よっしー
よっしー

何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました