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

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

このコミットは、Go言語の初期のflagパッケージ(src/lib/flag.go)におけるコマンドライン引数解析の挙動を修正するものです。具体的には、単一のハイフン(-)が引数として与えられた際のフラグ解析の停止ロジックを改善し、その挙動をドキュメントに明記しています。これにより、flagパッケージがより標準的なコマンドライン引数解析の慣習に沿うようになります。

コミット

commit c5f4867ffaffc29f9f99c913916ffc9991750d42
Author: Russ Cox <rsc@golang.org>
Date:   Tue Nov 18 17:23:11 2008 -0800

    stop flag reading before lone - arg.

    R=r
    DELTA=5  (3 added, 0 deleted, 2 changed)
    OCL=19520
    CL=19529

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

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

元コミット内容

stop flag reading before lone - arg.

R=r
DELTA=5  (3 added, 0 deleted, 2 changed)
OCL=19520
CL=19529

変更の背景

コマンドライン引数の解析において、単一のハイフン(-)は特別な意味を持つことがよくあります。例えば、多くのUnix系コマンドでは、-は標準入力または標準出力を意味するプレースホルダーとして使用されます。また、--はそれ以降の引数をすべて非フラグ引数として扱うことを示すターミネータとして機能します。

このコミット以前のflagパッケージの実装では、これらの慣習に対する扱いが不明確であったか、あるいは標準的な挙動と異なっていた可能性があります。特に、単一のハイフンがフラグとして誤って解釈されたり、フラグ解析の停止条件が曖昧であったりする問題があったと考えられます。

この変更の背景には、Go言語の標準ライブラリとして提供されるflagパッケージが、既存のコマンドラインツールの慣習に則り、より堅牢で予測可能な挙動を提供する必要があったという意図があります。これにより、ユーザーがGoで作成したコマンドラインツールが、他の一般的なツールと同様に直感的に動作することが期待されます。

前提知識の解説

コマンドライン引数とフラグ

コマンドライン引数とは、プログラムを実行する際に、そのプログラムに渡される追加情報のことです。これらは通常、プログラム名の後にスペース区切りで記述されます。 フラグ(またはオプション)は、特定の機能の有効化/無効化や、値の設定を行うための引数の一種です。

フラグの一般的な慣習

  • 単一ハイフン (-):
    • 通常、短い形式のフラグ(例: -v for verbose)に使用されます。
    • また、多くのUnix系コマンドでは、ファイル名の代わりに単一のハイフンが使われると、標準入力(読み込み時)または標準出力(書き込み時)を意味します。これは、パイプ処理と組み合わせて非常に強力な機能を提供します。
    • このコミットの文脈では、単一のハイフンが「非フラグ引数」として扱われ、フラグ解析を停止させる役割を持つことが重要です。
  • 二重ハイフン (--):
    • 通常、長い形式のフラグ(例: --verbose)に使用されます。
    • 最も重要なのは、--自体がコマンドライン引数リストに現れた場合、それ以降のすべての引数は、たとえハイフンで始まっていてもフラグとして解釈されず、通常の非フラグ引数として扱われるという慣習です。これは、ファイル名などがフラグと誤解されるのを防ぐために使用されます。

Go言語のflagパッケージ

Go言語の標準ライブラリには、コマンドラインフラグを解析するためのflagパッケージが用意されています。このパッケージは、プログラムがコマンドラインから受け取った引数を、定義されたフラグに基づいて自動的に解析し、対応する変数に値を設定する機能を提供します。

このコミットで変更されているsrc/lib/flag.goは、Go言語の初期段階におけるflagパッケージの実装であり、現在のgo/src/flagパッケージの前身にあたります。基本的な機能は共通していますが、初期の設計段階での細かな挙動の調整が行われていたことが伺えます。

技術的詳細

このコミットの技術的な核心は、flagパッケージがコマンドライン引数をどのように「フラグ」と「非フラグ引数」に区別し、いつフラグ解析を停止するかというロジックの改善にあります。

変更前は、ドキュメントに「A lone -- terminates the parsing of the command line.」(単一の--がコマンドラインの解析を終了させる)とだけ記述されていました。これは--の役割を正しく説明していますが、単一のハイフン(-)の扱いについては言及がありませんでした。

変更後は、ドキュメントが「Flag parsing stops just before the first non-flag argument ("-" is a non-flag argument) or after the terminator "--".」(フラグ解析は、最初の非フラグ引数(「-」は非フラグ引数である)の直前、またはターミネータ「--」の後に停止する)と更新されました。

この変更は以下の重要な意味を持ちます。

  1. 単一ハイフン(-)の扱い: 明示的に「-は非フラグ引数である」と定義されました。これにより、プログラムがコマンドラインで-を受け取った場合、それはフラグではなく、通常の引数(例えば、標準入力/出力を示すファイル名)として扱われるべきであることが明確になります。
  2. フラグ解析の停止条件の明確化: フラグ解析は、--が現れた場合だけでなく、最初の非フラグ引数(特に-)の直前でも停止するようになりました。これは、多くのUnix系コマンドラインツールが採用している標準的な挙動であり、ユーザーが期待する動作に合致します。例えば、mycommand -a -b - file1 file2のようなコマンドラインでは、-以降のfile1file2はフラグではなくファイル名として扱われるべきです。この変更により、flagパッケージはそのようなシナリオで正しく動作するようになります。

コードの変更点もこのドキュメントの変更と一致しています。ParseOne関数内で、引数sの長さが1(つまりs-)の場合の戻り値が-1からindexに変更されています。

  • return false, -1: これは、-がフラグとして認識されず、かつそれ以降の解析も停止することを示唆していました。しかし、-1という値は、次の引数のインデックスとしては不適切であり、何らかのエラーや特殊な状態を示す可能性がありました。
  • return false, index: これは、-自体はフラグではない(false)が、その引数(index)からフラグではない引数が始まることを示しています。つまり、-はフラグ解析の終了点を示すマーカーとして機能し、その-自体は非フラグ引数として後続の処理に渡されるべきであることを意味します。これにより、flagパッケージの呼び出し元は、-以降の引数を適切に処理できるようになります。

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

src/lib/flag.go ファイルの以下の2箇所が変更されています。

  1. コメントの変更 (行 32-35):

    --- a/src/lib/flag.go
    +++ b/src/lib/flag.go
    @@ -32,7 +32,10 @@ package flag
     *		-flag=x
     *		-flag x
     *	One or two minus signs may be used; they are equivalent.
    - *	A lone -- terminates the parsing of the command line.
    + *
    + *	Flag parsing stops just before the first non-flag argument
    + *	("-" is a non-flag argument) or after the terminator "--".
    + *
     *	Integer flags accept 1234, 0664, 0x1234 and may be negative.
     *	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
     */
    
  2. ParseOne関数のロジック変更 (行 397-400):

    --- a/src/lib/flag.go
    +++ b/src/lib/flag.go
    @@ -397,7 +400,7 @@ func (f *Flags) ParseOne(index int) (ok bool, next int)\n     }\n     num_minuses := 1;\n     if len(s) == 1 {\n-    	return false, -1
    +    	return false, index
     }\n     if s[1] == '-' {\n     	num_minuses++;
    

コアとなるコードの解説

コメントの変更

この変更は、flagパッケージのユーザーに対する最も直接的な影響を持つ部分です。以前のドキュメントでは、--がフラグ解析を終了させることのみが述べられていました。しかし、この変更により、単一のハイフン(-)もまた「非フラグ引数」として扱われ、その直前でフラグ解析が停止するという、より詳細で正確な挙動が明記されました。これは、flagパッケージがUnix系のコマンドラインツールの慣習に準拠していることを明確にするものです。

ParseOne関数のロジック変更

ParseOne関数は、コマンドライン引数リストから次の単一の引数を解析し、それがフラグであるかどうか、そして次の解析を開始すべきインデックスを返す役割を担っています。

変更された行は以下の部分です。

    if len(s) == 1 {
    	return false, index // 変更後
    }

ここでsは現在解析中のコマンドライン引数文字列です。len(s) == 1かつs[0]がハイフンである場合(つまりsが単一の-である場合)、この条件が真となります。

  • 変更前 (return false, -1): 単一の-が検出された場合、それはフラグではない(false)と判断され、次のインデックスとして-1が返されていました。-1という値は、通常、エラーや「これ以上解析する引数がない」といった特殊な状態を示すために使われることがあります。この挙動では、-自体が非フラグ引数として後続の処理に渡されるべきなのか、それとも単に解析が終了したことを示すだけなのかが曖昧でした。

  • 変更後 (return false, index): 単一の-が検出された場合、それはフラグではない(false)と判断されますが、次のインデックスとして現在のindexが返されます。これは、ParseOne関数が現在の引数(-)をフラグとして消費しなかったことを意味します。したがって、呼び出し元はindexが指すこの-を、フラグではない通常の引数として処理を続行することができます。これにより、-が標準入力/出力を意味するようなシナリオで、プログラムが-を正しく非フラグ引数として認識し、それに応じた処理を行うことが可能になります。

この変更は、flagパッケージがより柔軟に、かつ標準的なコマンドライン引数の慣習に沿って動作するための重要な修正です。

関連リンク

参考にした情報源リンク

このコミットは、Go言語の初期のflagパッケージ(src/lib/flag.go)におけるコマンドライン引数解析の挙動を修正するものです。具体的には、単一のハイフン(-)が引数として与えられた際のフラグ解析の停止ロジックを改善し、その挙動をドキュメントに明記しています。これにより、flagパッケージがより標準的なコマンドライン引数解析の慣習に沿うようになります。

コミット

commit c5f4867ffaffc29f9f99c913916ffc9991750d42
Author: Russ Cox <rsc@golang.org>
Date:   Tue Nov 18 17:23:11 2008 -0800

    stop flag reading before lone - arg.

    R=r
    DELTA=5  (3 added, 0 deleted, 2 changed)
    OCL=19520
    CL=19529

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

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

元コミット内容

stop flag reading before lone - arg.

R=r
DELTA=5  (3 added, 0 deleted, 2 changed)
OCL=19520
CL=19529

変更の背景

コマンドライン引数の解析において、単一のハイフン(-)は特別な意味を持つことがよくあります。例えば、多くのUnix系コマンドでは、-は標準入力または標準出力を意味するプレースホルダーとして使用されます。また、--はそれ以降の引数をすべて非フラグ引数として扱うことを示すターミネータとして機能します。

このコミット以前のflagパッケージの実装では、これらの慣習に対する扱いが不明確であったか、あるいは標準的な挙動と異なっていた可能性があります。特に、単一のハイフンがフラグとして誤って解釈されたり、フラグ解析の停止条件が曖昧であったりする問題があったと考えられます。

この変更の背景には、Go言語の標準ライブラリとして提供されるflagパッケージが、既存のコマンドラインツールの慣習に則り、より堅牢で予測可能な挙動を提供する必要があったという意図があります。これにより、ユーザーがGoで作成したコマンドラインツールが、他の一般的なツールと同様に直感的に動作することが期待されます。

前提知識の解説

コマンドライン引数とフラグ

コマンドライン引数とは、プログラムを実行する際に、そのプログラムに渡される追加情報のことです。これらは通常、プログラム名の後にスペース区切りで記述されます。 フラグ(またはオプション)は、特定の機能の有効化/無効化や、値の設定を行うための引数の一種です。

フラグの一般的な慣習

  • 単一ハイフン (-):
    • 通常、短い形式のフラグ(例: -v for verbose)に使用されます。
    • また、多くのUnix系コマンドでは、ファイル名の代わりに単一のハイフンが使われると、標準入力(読み込み時)または標準出力(書き込み時)を意味します。これは、パイプ処理と組み合わせて非常に強力な機能を提供します。
    • このコミットの文脈では、単一のハイフンが「非フラグ引数」として扱われ、フラグ解析を停止させる役割を持つことが重要です。
  • 二重ハイフン (--):
    • 通常、長い形式のフラグ(例: --verbose)に使用されます。
    • 最も重要なのは、--自体がコマンドライン引数リストに現れた場合、それ以降のすべての引数は、たとえハイフンで始まっていてもフラグとして解釈されず、通常の非フラグ引数として扱われるという慣習です。これは、ファイル名などがフラグと誤解されるのを防ぐために使用されます。

Go言語のflagパッケージ

Go言語の標準ライブラリには、コマンドラインフラグを解析するためのflagパッケージが用意されています。このパッケージは、プログラムがコマンドラインから受け取った引数を、定義されたフラグに基づいて自動的に解析し、対応する変数に値を設定する機能を提供します。

このコミットで変更されているsrc/lib/flag.goは、Go言語の初期段階におけるflagパッケージの実装であり、現在のgo/src/flagパッケージの前身にあたります。基本的な機能は共通していますが、初期の設計段階での細かな挙動の調整が行われていたことが伺えます。

技術的詳細

このコミットの技術的な核心は、flagパッケージがコマンドライン引数をどのように「フラグ」と「非フラグ引数」に区別し、いつフラグ解析を停止するかというロジックの改善にあります。

変更前は、ドキュメントに「A lone -- terminates the parsing of the command line.」(単一の--がコマンドラインの解析を終了させる)とだけ記述されていました。これは--の役割を正しく説明していますが、単一のハイフン(-)の扱いについては言及がありませんでした。

変更後は、ドキュメントが「Flag parsing stops just before the first non-flag argument ("-" is a non-flag argument) or after the terminator "--".」(フラグ解析は、最初の非フラグ引数(「-」は非フラグ引数である)の直前、またはターミネータ「--」の後に停止する)と更新されました。

この変更は以下の重要な意味を持ちます。

  1. 単一ハイフン(-)の扱い: 明示的に「-は非フラグ引数である」と定義されました。これにより、プログラムがコマンドラインで-を受け取った場合、それはフラグではなく、通常の引数(例えば、標準入力/出力を示すファイル名)として扱われるべきであることが明確になります。
  2. フラグ解析の停止条件の明確化: フラグ解析は、--が現れた場合だけでなく、最初の非フラグ引数(特に-)の直前でも停止するようになりました。これは、多くのUnix系コマンドラインツールが採用している標準的な挙動であり、ユーザーが期待する動作に合致します。例えば、mycommand -a -b - file1 file2のようなコマンドラインでは、-以降のfile1file2はフラグではなくファイル名として扱われるべきです。この変更により、flagパッケージはそのようなシナリオで正しく動作するようになります。

コードの変更点もこのドキュメントの変更と一致しています。ParseOne関数内で、引数sの長さが1(つまりs-)の場合の戻り値が-1からindexに変更されています。

  • return false, -1: これは、-がフラグとして認識されず、かつそれ以降の解析も停止することを示唆していました。しかし、-1という値は、次の引数のインデックスとしては不適切であり、何らかのエラーや特殊な状態を示す可能性がありました。
  • return false, index: これは、-自体はフラグではない(false)が、その引数(index)からフラグではない引数が始まることを示しています。つまり、-はフラグ解析の終了点を示すマーカーとして機能し、その-自体は非フラグ引数として後続の処理に渡されるべきであることを意味します。これにより、flagパッケージの呼び出し元は、-以降の引数を適切に処理できるようになります。

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

src/lib/flag.go ファイルの以下の2箇所が変更されています。

  1. コメントの変更 (行 32-35):

    --- a/src/lib/flag.go
    +++ b/src/lib/flag.go
    @@ -32,7 +32,10 @@ package flag
     *		-flag=x
     *		-flag x
     *	One or two minus signs may be used; they are equivalent.
    - *	A lone -- terminates the parsing of the command line.
    + *
    + *	Flag parsing stops just before the first non-flag argument
    + *	("-" is a non-flag argument) or after the terminator "--".
    + *
     *	Integer flags accept 1234, 0664, 0x1234 and may be negative.
     *	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
     */
    
  2. ParseOne関数のロジック変更 (行 397-400):

    --- a/src/lib/flag.go
    +++ b/src/lib/flag.go
    @@ -397,7 +400,7 @@ func (f *Flags) ParseOne(index int) (ok bool, next int)\n     }\n     num_minuses := 1;\n     if len(s) == 1 {\n-    	return false, -1
    +    	return false, index
     }\n     if s[1] == '-' {\n     	num_minuses++;
    

コアとなるコードの解説

コメントの変更

この変更は、flagパッケージのユーザーに対する最も直接的な影響を持つ部分です。以前のドキュメントでは、--がフラグ解析を終了させることのみが述べられていました。しかし、この変更により、単一のハイフン(-)もまた「非フラグ引数」として扱われ、その直前でフラグ解析が停止するという、より詳細で正確な挙動が明記されました。これは、flagパッケージがUnix系のコマンドラインツールの慣習に準拠していることを明確にするものです。

ParseOne関数のロジック変更

ParseOne関数は、コマンドライン引数リストから次の単一の引数を解析し、それがフラグであるかどうか、そして次の解析を開始すべきインデックスを返す役割を担っています。

変更された行は以下の部分です。

    if len(s) == 1 {
    	return false, index // 変更後
    }

ここでsは現在解析中のコマンドライン引数文字列です。len(s) == 1かつs[0]がハイフンである場合(つまりsが単一の-である場合)、この条件が真となります。

  • 変更前 (return false, -1): 単一の-が検出された場合、それはフラグではない(false)と判断され、次のインデックスとして-1が返されていました。-1という値は、通常、エラーや「これ以上解析する引数がない」といった特殊な状態を示すために使われることがあります。この挙動では、-自体が非フラグ引数として後続の処理に渡されるべきなのか、それとも単に解析が終了したことを示すだけなのかが曖昧でした。

  • 変更後 (return false, index): 単一の-が検出された場合、それはフラグではない(false)と判断されますが、次のインデックスとして現在のindexが返されます。これは、ParseOne関数が現在の引数(-)をフラグとして消費しなかったことを意味します。したがって、呼び出し元はindexが指すこの-を、フラグではない通常の引数として処理を続行することができます。これにより、-が標準入力/出力を意味するようなシナリオで、プログラムが-を正しく非フラグ引数として認識し、それに応じた処理を行うことが可能になります。

この変更は、flagパッケージがより柔軟に、かつ標準的なコマンドライン引数の慣習に沿って動作するための重要な修正です。

関連リンク

参考にした情報源リンク