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

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

このコミットは、Go言語のコマンドラインツール go test の挙動に関するドキュメントと実装の変更を扱っています。具体的には、go test が認識しないフラグ(オプション)をコマンドラインで指定する際の正しい位置について、ユーザーに明確な指示を与えるための修正です。

コミット

commit 482f3e8481465bccefea2a0093e5fbeefb30bb29
Author: Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au>
Date:   Fri Feb 8 16:00:59 2013 -0500

    cmd/go: indicate that flags unrecognized by 'go test' must follow package specification
    
    R=rsc, minux.ma
    CC=golang-dev
    https://golang.org/cl/7300063

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

https://github.com/golang/go/commit/482f3e8481465bccefea2a0093e5fbeefb30bb29

元コミット内容

cmd/go: indicate that flags unrecognized by 'go test' must follow package specification

このコミットメッセージは、go test コマンドが認識しないフラグは、パッケージ指定の後に配置する必要があることを示す、という変更の意図を簡潔に述べています。

変更の背景

Go言語の go test コマンドは、テストの実行、ベンチマーク、プロファイリングなど、Goプロジェクトのテストに関連する多岐にわたる機能を提供します。このコマンドは、Goツールチェーンの一部として、特定のフラグ(例: -v で詳細出力、-bench でベンチマーク実行)を認識し、それに応じて動作を変更します。

しかし、go test コマンド自体が認識しないフラグを、テストバイナリ(go test がコンパイルして実行するテストプログラム)に渡したい場合があります。例えば、テストバイナリが独自のコマンドライン引数を処理するように設計されている場合などです。

このコミットが作成された背景には、ユーザーが go test コマンドに、go test 自身が処理すべきフラグと、テストバイナリに渡すべきフラグを混同して指定してしまうという問題があったと考えられます。Goのコマンドライン引数処理の慣習として、コマンド自身が処理する引数と、そのコマンドが起動するサブプロセスに渡す引数を区別するために、-- のようなセパレータを使用したり、引数の順序に特定のルールを設けたりすることが一般的です。

このコミットは、go test が認識しないフラグをテストバイナリに正しく渡すための明確なルールを導入し、ユーザーの混乱を避けることを目的としています。具体的には、「go test が認識しないフラグは、パッケージ指定の後に配置しなければならない」というルールを明文化し、ドキュメントとコードコメントに追加することで、ユーザーが意図した通りにテストを実行できるように改善しています。

前提知識の解説

Go言語の go test コマンド

go test は、Go言語の標準的なテストツールです。Goのソースコード内に記述されたテスト関数(TestXxxBenchmarkXxxExampleXxx など)を検出し、それらをコンパイルしてテストバイナリを生成し、実行します。

go test コマンドは、以下のような一般的な形式で実行されます。

go test [flags] [packages]
  • [flags]: go test コマンド自身が解釈するフラグです。例:
    • -v: 詳細なテスト結果を出力します。
    • -run <regexp>: 指定された正規表現にマッチするテストのみを実行します。
    • -bench <regexp>: 指定された正規表現にマッチするベンチマークのみを実行します。
    • -cpu <list>: 指定されたGOMAXPROCS値でテストを実行します。
    • -cover: カバレッジ情報を収集します。
  • [packages]: テストを実行するパッケージを指定します。例: ./... (カレントディレクトリ以下の全パッケージ)、./my/package

コマンドライン引数のパース

多くのコマンドラインツールでは、引数のパース(解析)に特定の規則があります。特に、コマンド自身が処理する引数と、そのコマンドが起動する別のプログラムに渡す引数を区別するメカニズムが重要になります。

一般的な慣習として、以下のようなパターンがあります。

  1. -- セパレータ: 一部のコマンドでは、-- を使用して、それ以降の引数をサブコマンドや別のプログラムに渡すことを示します。例: git commit -m "message" -- -s (ここで -sgit commit ではなく、エディタに渡される)。
  2. 引数の順序: 引数の種類によって、コマンドライン上での出現順序が厳密に定められている場合があります。例えば、コマンド自身のフラグはコマンド名の直後に、ファイルパスやサブプログラムへの引数はその後に続く、といった規則です。

このコミットは、go test における後者の「引数の順序」に関するルールを明確にしています。go test が認識しないフラグは、go test コマンド自身が処理するのではなく、コンパイルされたテストバイナリに渡されます。このとき、それらの「認識されないフラグ」は、パッケージ指定の後に置かれる必要がある、というルールです。

例えば、go test -v ./my/package -myflag value のように指定した場合、-vgo test が処理し、-myflag valuemy/package のテストバイナリに渡されることになります。もし -myflag value がパッケージ指定の前に置かれた場合、go test はそれを自身のフラグとして解釈しようとし、認識できないためにエラーとなるか、意図しない挙動を引き起こす可能性があります。

技術的詳細

このコミットの技術的な詳細は、主にGoツールチェーンの cmd/go パッケージにおける go test コマンドの引数パースロジックと、そのドキュメント化に焦点を当てています。

go test コマンドは、内部的に flag パッケージを使用して自身のフラグを解析します。しかし、go test は単に自身のフラグを処理するだけでなく、テストバイナリに渡すべきフラグも適切に分離して処理する必要があります。

コミットメッセージにある「Flags not recognized by 'go test' must be placed after any specified packages.」という指示は、go test のコマンドライン引数処理の内部的な仕組みに基づいています。

  1. go test は、まず自身のフラグ(例: -v, -run)を解析します。
  2. 次に、パッケージ指定(例: ./..., github.com/foo/bar)を解析します。
  3. パッケージ指定の後に続く引数で、かつ go test 自身が認識しないフラグは、テストバイナリに渡すための引数として扱われます。

この順序が重要であり、もし認識されないフラグがパッケージ指定の前に置かれると、go test はそれを自身のフラグとして解釈しようとし、結果として「不明なフラグ」エラーを発生させるか、あるいは誤ってパッケージ名の一部として解釈してしまう可能性があります。

このコミットは、この挙動をユーザーに明確に伝えるために、src/cmd/go/doc.go(Goコマンドのヘルプドキュメント)と src/cmd/go/test.gogo test コマンドの実装ファイル内のコメント)の両方に同じ注意書きを追加しています。これにより、ユーザーは go help test コマンドを実行した際や、ソースコードを読んだ際に、この重要なルールを理解できるようになります。

これは、Goツールチェーンのユーザーエクスペリエンスを向上させるための、小さなしかし重要なドキュメントとコードの整合性に関する改善です。

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

このコミットによる変更は、以下の2つのファイルに限定されています。

  1. src/cmd/go/doc.go
  2. src/cmd/go/test.go

それぞれのファイルで、全く同じ行が追加されています。

--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -766,6 +766,8 @@ will compile the test binary and then run it as
 The test flags that generate profiles also leave the test binary in pkg.test
 for use when analyzing the profiles.
 
+Flags not recognized by 'go test' must be placed after any specified packages.
+
 
 Description of testing functions
 
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -167,6 +167,8 @@ will compile the test binary and then run it as
 
 The test flags that generate profiles also leave the test binary in pkg.test
 for use when analyzing the profiles.
+\n+Flags not recognized by 'go test' must be placed after any specified packages.
 `,
  }
 

コアとなるコードの解説

追加された行は以下の通りです。

Flags not recognized by 'go test' must be placed after any specified packages.

この行は、go test コマンドのドキュメントと、go test コマンドの内部的な説明コメントの両方に追加されました。

  • src/cmd/go/doc.go: このファイルは、go help コマンドで表示されるGoコマンド全体のドキュメントを生成するためのソースです。このファイルにこの行を追加することで、ユーザーが go help test を実行した際に、この重要な情報が直接表示されるようになります。これは、ユーザーがコマンドライン引数の正しい使い方を理解するための主要な情報源となります。
  • src/cmd/go/test.go: このファイルは go test コマンドの実際のロジックを実装しています。このファイル内のコメントにこの行を追加することは、主に開発者向けです。go test のコードを将来的に変更する開発者が、コマンドライン引数のパースに関するこの重要な規則を認識し、それに従ってコードを維持・変更するための注意喚起となります。

この変更は、コードの機能的な挙動を変更するものではなく、既存の挙動に関するドキュメントと内部コメントを改善し、ユーザーと開発者の両方にとっての明確性を高めることを目的としています。これにより、go test コマンドの使い方がより明確になり、誤った引数指定による混乱やエラーが減少することが期待されます。

関連リンク

参考にした情報源リンク