Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14457] ファイルの概要

このコミットは、Go言語のコマンドラインツール gotest サブコマンドにおけるユーザーへのヒント表示を改善するものです。具体的には、go test 実行時に、将来のテストを高速化するために go test -i の使用を促すメッセージが表示される際、もし go test -race オプションが有効になっている場合は、その -race オプションもヒントに含めるように変更されています。これにより、ユーザーは go test -race -i のように、-race オプションを維持したままインストールを高速化できることをより明確に理解できます。

コミット

commit f142deee959dbc753b23efc23f60bd755498ec3d
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri Nov 23 19:29:22 2012 +0800

    cmd/go: show -race if necessary when giving "go test -i" hint
    
    R=golang-dev, dsymonds
    CC=golang-dev
    https://golang.org/cl/6851100

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/f142deee959dbc753b23efc23f60bd755498ec3d

元コミット内容

cmd/go: show -race if necessary when giving "go test -i" hint

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/6851100

変更の背景

Go言語の go test コマンドは、テストを実行する前に、テスト対象のパッケージとその依存関係をビルドします。このビルドプロセスは、特に大規模なプロジェクトや多くの依存関係を持つ場合に時間がかかることがあります。go test -i オプションは、テストに必要なパッケージをインストール(ビルドしてキャッシュ)することで、その後のテスト実行を高速化する目的で使用されます。

しかし、Goにはデータ競合を検出するための -race オプションも存在します。これは、並行処理における潜在的なバグを見つけるのに非常に有用なツールです。ユーザーが go test -race を使用してテストを実行している場合、システムは go test -i を使ってパッケージをインストールするようヒントを出すことがありました。このとき、元のヒントメッセージは単に go test -i を推奨するだけで、-race オプションが考慮されていませんでした。

この状況では、ユーザーがヒントに従って go test -i を実行すると、-race オプションなしでパッケージがビルド・インストールされてしまいます。その結果、次に go test -race を実行した際に、-race オプション付きで再度パッケージがビルドされることになり、ビルド時間の短縮という go test -i の本来の目的が損なわれる可能性がありました。

このコミットは、このような不整合を解消し、ユーザーが -race オプションを使用している場合に、より適切で効率的なヒントを提供することを目的としています。つまり、-race オプションが有効な場合は、ヒントメッセージにも -race を含めることで、ユーザーが go test -race -i のように、-race オプションを維持したままパッケージをインストールできるようにします。

前提知識の解説

go test コマンド

go test は、Go言語のパッケージのテストを実行するためのコマンドです。指定されたパッケージ内の _test.go ファイルに記述されたテスト関数(TestXxxBenchmarkXxx、``ExampleXxx`)を実行します。

go test -i オプション

go test -i は "install" の略で、テストを実行する前に、テスト対象のパッケージとその依存関係をビルドし、インストールキャッシュに保存します。これにより、その後のテスト実行時に同じパッケージが再ビルドされるのを防ぎ、テストの実行時間を短縮することができます。これは、特に依存関係が多いプロジェクトや、頻繁にテストを実行する場合に有用です。

go test -race オプション

go test -race は、Goの組み込みのデータ競合検出器(Race Detector)を有効にしてテストを実行します。データ競合は、複数のゴルーチンが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みである場合に発生するバグです。Race Detectorは、実行時にこれらの競合を検出し、レポートします。-race オプションを有効にすると、ビルドされるバイナリに競合検出のための追加のインストゥルメンテーションが組み込まれるため、通常のビルドよりも時間がかかり、生成されるバイナリのサイズも大きくなります。

Goのビルドキャッシュ

Goは、ビルドされたパッケージやモジュールをキャッシュする仕組みを持っています。これにより、変更がない限り同じコードを再ビルドする手間を省き、開発プロセスを高速化します。go test -i はこのキャッシュメカニズムを利用して、テストに必要な依存関係を事前にビルド・インストールすることで、テスト実行時のビルドステップをスキップできるようにします。

技術的詳細

この変更は、src/cmd/go/test.go ファイル内の runTest 関数にあります。この関数は go test コマンドの主要なロジックを処理します。

変更の核心は、go test -i のヒントメッセージを生成する際に、buildRace という内部変数の状態を確認することです。buildRace は、現在の go test の実行が -race オプション付きで行われているかどうかを示すブール値です。

変更前は、ヒントメッセージは常に go test -i の形式で生成されていました。 変更後は、buildRacetrue の場合、extraOpts という文字列変数に "-race " を設定します。buildRacefalse の場合は、extraOpts は空文字列のままです。 そして、この extraOptsfmt.Fprintf で出力するヒントメッセージに挿入することで、-race オプションが有効な場合にのみ、ヒントメッセージが go test -race -i の形式になるようにしています。

これにより、ユーザーが -race オプションを使用してテストを実行している場合でも、提供されるヒントが現在のビルド設定と一致し、-race オプション付きでパッケージをインストールするよう促されるため、無駄な再ビルドを防ぎ、開発体験が向上します。

コアとなるコードの変更箇所

--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -379,7 +379,11 @@ func runTest(cmd *Command, args []string) {
 		if args != "" {
 			args = " " + args
 		}
-		fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\\n\\n", args)
+		extraOpts := ""
+		if buildRace {
+			extraOpts = "-race "
+		}
+		fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\\n\\n", extraOpts, args)
 	}

 	b.do(root)

コアとなるコードの解説

変更は src/cmd/go/test.go ファイルの runTest 関数内、具体的には379行目付近にあります。

  1. 変更前のコード:

    fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\\n\\n", args)
    

    この行は、標準エラー出力に「go test -i を使ってこれらのパッケージをインストールすると、将来のテストが高速化されます。」というヒントメッセージを出力していました。%s には、元の go test コマンドに渡された追加の引数(例: パッケージ名)が含まれます。

  2. 変更後のコード:

    extraOpts := ""
    if buildRace {
    	extraOpts = "-race "
    }
    fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\\n\\n", extraOpts, args)
    
    • extraOpts := "":まず、extraOpts という新しい文字列変数を空で初期化します。この変数は、ヒントメッセージに含める追加のオプション(この場合は -race)を保持します。
    • if buildRace { extraOpts = "-race " }buildRace は、現在の go test の実行が -race オプション付きで行われているかどうかを示す内部フラグです。もし buildRacetrue であれば、extraOpts"-race " という文字列(-race オプションとそれに続くスペース)が代入されます。これにより、ヒントメッセージに -race が含まれるようになります。
    • fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\\n\\n", extraOpts, args):最後に、ヒントメッセージのフォーマット文字列が変更され、%s のプレースホルダーが追加されました。この新しいプレースホルダーには extraOpts の値が挿入されます。
      • buildRacetrue の場合、メッセージは go test -race -i... となります。
      • buildRacefalse の場合、extraOpts は空文字列のままなので、メッセージは go test -i... となり、以前と同じ動作を維持します。

この変更により、go test -race を使用しているユーザーに対して、より文脈に合った正確なヒントが提供されるようになり、開発ワークフローの効率が向上します。

関連リンク

参考にした情報源リンク