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

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

このコミットは、Go言語のコマンドラインツール go tool におけるエラーメッセージの修正に関するものです。具体的には、存在しないツール名や不正なツール名が指定された際に表示されるエラーメッセージにおいて、誤った変数 tool を参照していた箇所を、正しい変数 toolName に修正しています。これにより、ユーザーに対してより正確なエラー情報が提供されるようになります。

コミット

commit e489ab8ecc36c8b2caeeda662e6d7b57b64e8475
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Thu Feb 2 23:52:30 2012 +0100

    cmd/go: fix error message on non-existing tools.
    
    R=golang-dev, rsc
    CC=golang-dev, remy
    https://golang.org/cl/5617053

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

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

元コミット内容

cmd/go: fix error message on non-existing tools.

このコミットは、go tool コマンドが、存在しないツールや不正なツール名が指定された場合に表示するエラーメッセージを修正します。

変更の背景

go tool コマンドは、Go言語のツールチェインに含まれる様々な補助ツール(例: go tool vet, go tool pprof など)を実行するための汎用コマンドです。このコマンドは、指定されたツール名に基づいて、対応する実行ファイルを検索し、実行します。

このコミットが行われる前は、go tool コマンドが不正なツール名や存在しないツール名を処理する際に、エラーメッセージ内で表示されるツール名が正しくないという問題がありました。具体的には、ユーザーが入力したツール名ではなく、別の(おそらくは内部的な処理で使われる)変数の値が表示されてしまうことがありました。これは、ユーザーがエラーの原因を特定する上で混乱を招く可能性がありました。

この修正は、ユーザーエクスペリエンスの向上を目的としています。正確なエラーメッセージは、ユーザーが問題を迅速に理解し、解決するために不可欠です。

前提知識の解説

go tool コマンド

go tool は、Go言語のビルドシステムに組み込まれている様々な低レベルツールを実行するためのコマンドです。例えば、go tool compile はGoソースコードをコンパイルし、go tool link はコンパイルされたオブジェクトファイルをリンクします。これらのツールは通常、go buildgo run のような高レベルなコマンドによって内部的に呼び出されますが、開発者が直接呼び出すことも可能です。

os.Stderr

os.Stderr は、Go言語の os パッケージで提供される標準エラー出力へのファイル記述子です。プログラムがエラーメッセージや診断情報を出力する際に使用されます。通常、これらのメッセージはコンソールに表示されます。

fmt.Fprintf

fmt.Fprintf は、Go言語の fmt パッケージで提供される関数で、指定された io.Writer (この場合は os.Stderr)にフォーマットされた文字列を出力します。C言語の fprintf に似ており、フォーマット指定子(例: %q)を使用して変数の値を埋め込むことができます。

%q フォーマット指定子

%qfmt パッケージのフォーマット指定子の一つで、文字列をGoの構文でクォート(引用符で囲む)して出力します。これにより、文字列内の特殊文字(例: スペース、改行)がエスケープされ、デバッグやログ出力において文字列の境界が明確になります。

os.Stat

os.Stat は、Go言語の os パッケージで提供される関数で、指定されたパスのファイル情報を取得します。ファイルが存在しない場合や、アクセス権がない場合などにはエラーを返します。この関数は、ファイルやディレクトリの存在確認によく使用されます。

setExitStatus

setExitStatus は、Goコマンドラインツール内で定義されている可能性のあるヘルパー関数で、プログラムの終了ステータスを設定するために使用されます。終了ステータスは、プログラムが正常に終了したか、またはどのような種類のエラーで終了したかを示す整数値です。慣例として、0は成功、非ゼロはエラーを示します。

変数のスコープとシャドーイング

Go言語では、変数は宣言されたブロック({} で囲まれた範囲)内で有効です。内側のブロックで外側のブロックと同じ名前の変数を宣言すると、内側のブロックでは新しい変数が優先され、外側の変数は「シャドーイング」されます。このコミットの文脈では、tooltoolName という似たような名前の変数が存在し、どちらがエラーメッセージに表示されるべきかという問題が関係しています。

技術的詳細

このコミットは、src/cmd/go/tool.go ファイル内の runTool 関数における2つの fmt.Fprintf 呼び出しを修正しています。

元のコードでは、不正なツール名が検出された場合(文字がアルファベット小文字または数字でない場合)と、ツールが存在しない場合(os.Stat がエラーを返す場合)に、エラーメッセージを標準エラー出力に書き出していました。

問題は、これらのエラーメッセージが tool という変数を参照していた点にあります。しかし、runTool 関数内で実際にユーザーが指定したツール名を処理するために使われていた変数は toolName でした。

例えば、ユーザーが go tool mytool! のように不正なツール名を指定した場合、tool 変数には予期しない値が入っている可能性があり、結果として go tool: bad tool name "" のように空文字列が表示されたり、あるいは全く関係のない値が表示されたりすることがありました。同様に、go tool nonexist のように存在しないツール名を指定した場合も、go tool: no such tool "" のように表示される可能性がありました。

この修正により、fmt.Fprintf の引数が tool から toolName に変更されました。toolName は、runTool 関数の冒頭で args[0] から取得され、ユーザーが実際にコマンドラインで指定したツール名を正確に保持しています。

// 修正前
fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", tool)
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", tool)

// 修正後
fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName)
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", toolName)

この変更により、エラーメッセージは常にユーザーが入力したツール名を正確に反映するようになり、デバッグや問題解決が容易になります。これは、Goコマンドラインツールの堅牢性とユーザーフレンドリーさを向上させるための小さな、しかし重要な修正です。

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

--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -55,7 +55,7 @@ func runTool(cmd *Command, args []string) {
 		switch {
 		case 'a' <= c && c <= 'z', '0' <= c && c <= '9':
 		default:
-			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", tool)
+			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName)
 			setExitStatus(2)
 			return
 		}
@@ -63,7 +63,7 @@ func runTool(cmd *Command, args []string) {
 	toolPath := tool(toolName)
 	// Give a nice message if there is no tool with that name.
 	if _, err := os.Stat(toolPath); err != nil {
-		fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", tool)
+		fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", toolName)
 		setExitStatus(3)
 		return
 	}

コアとなるコードの解説

この変更は、src/cmd/go/tool.go ファイル内の runTool 関数にあります。

runTool 関数は、go tool コマンドが呼び出された際に、指定されたツールを実行する主要なロジックを含んでいます。

  1. 不正なツール名のチェック (行 55-60):

    		switch {
    		case 'a' <= c && c <= 'z', '0' <= c && c <= '9':
    		default:
    			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName) // 修正箇所
    			setExitStatus(2)
    			return
    		}
    

    この部分では、ツール名の各文字が有効な文字(アルファベット小文字または数字)であるかをチェックしています。もし無効な文字が含まれていた場合、"go tool: bad tool name %q\\n" というエラーメッセージを出力します。修正前はここで tool 変数を使用していましたが、修正後は toolName を使用することで、ユーザーが入力した不正なツール名が正確にエラーメッセージに表示されるようになりました。

  2. 存在しないツールのチェック (行 63-67):

    	toolPath := tool(toolName)
    	// Give a nice message if there is no tool with that name.
    	if _, err := os.Stat(toolPath); err != nil {
    		fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", toolName) // 修正箇所
    		setExitStatus(3)
    		return
    	}
    

    この部分では、toolName から構築された toolPath に対応する実行ファイルが実際に存在するかを os.Stat で確認しています。もしファイルが存在しない場合、"go tool: no such tool %q\\n" というエラーメッセージを出力します。ここでも同様に、修正前は tool 変数を使用していましたが、修正後は toolName を使用することで、ユーザーが指定した存在しないツール名が正確にエラーメッセージに表示されるようになりました。

この修正は、Go言語のコマンドラインツールのエラー報告の正確性を高め、ユーザーが問題をより効率的に診断できるようにするためのものです。

関連リンク

参考にした情報源リンク

このコミットは、Go言語のコマンドラインツール go tool におけるエラーメッセージの修正に関するものです。具体的には、存在しないツール名や不正なツール名が指定された際に表示されるエラーメッセージにおいて、誤った変数 tool を参照していた箇所を、正しい変数 toolName に修正しています。これにより、ユーザーに対してより正確なエラー情報が提供されるようになります。

コミット

commit e489ab8ecc36c8b2caeeda662e6d7b57b64e8475
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Thu Feb 2 23:52:30 2012 +0100

    cmd/go: fix error message on non-existing tools.
    
    R=golang-dev, rsc
    CC=golang-dev, remy
    https://golang.org/cl/5617053

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

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

元コミット内容

cmd/go: fix error message on non-existing tools.

このコミットは、go tool コマンドが、存在しないツールや不正なツール名が指定された場合に表示するエラーメッセージを修正します。

変更の背景

go tool コマンドは、Go言語のツールチェインに含まれる様々な補助ツール(例: go tool vet, go tool pprof など)を実行するための汎用コマンドです。このコマンドは、指定されたツール名に基づいて、対応する実行ファイルを検索し、実行します。

このコミットが行われる前は、go tool コマンドが不正なツール名や存在しないツール名を処理する際に、エラーメッセージ内で表示されるツール名が正しくないという問題がありました。具体的には、ユーザーが入力したツール名ではなく、別の(おそらくは内部的な処理で使われる)変数の値が表示されてしまうことがありました。これは、ユーザーがエラーの原因を特定する上で混乱を招く可能性がありました。

この修正は、ユーザーエクスペリエンスの向上を目的としています。正確なエラーメッセージは、ユーザーが問題を迅速に理解し、解決するために不可欠です。

前提知識の解説

go tool コマンド

go tool は、Go言語のビルドシステムに組み込まれている様々な低レベルツールを実行するためのコマンドです。例えば、go tool compile はGoソースコードをコンパイルし、go tool link はコンパイルされたオブジェクトファイルをリンクします。これらのツールは通常、go buildgo run のような高レベルなコマンドによって内部的に呼び出されますが、開発者が直接呼び出すことも可能です。

os.Stderr

os.Stderr は、Go言語の os パッケージで提供される標準エラー出力へのファイル記述子です。プログラムがエラーメッセージや診断情報を出力する際に使用されます。通常、これらのメッセージはコンソールに表示されます。

fmt.Fprintf

fmt.Fprintf は、Go言語の fmt パッケージで提供される関数で、指定された io.Writer (この場合は os.Stderr)にフォーマットされた文字列を出力します。C言語の fprintf に似ており、フォーマット指定子(例: %q)を使用して変数の値を埋め込むことができます。

%q フォーマット指定子

%qfmt パッケージのフォーマット指定子の一つで、文字列をGoの構文でクォート(引用符で囲む)して出力します。これにより、文字列内の特殊文字(例: スペース、改行)がエスケープされ、デバッグやログ出力において文字列の境界が明確になります。

os.Stat

os.Stat は、Go言語の os パッケージで提供される関数で、指定されたパスのファイル情報を取得します。ファイルが存在しない場合や、アクセス権がない場合などにはエラーを返します。この関数は、ファイルやディレクトリの存在確認によく使用されます。

setExitStatus

setExitStatus は、Goコマンドラインツール内で定義されている可能性のあるヘルパー関数で、プログラムの終了ステータスを設定するために使用されます。終了ステータスは、プログラムが正常に終了したか、またはどのような種類のエラーで終了したかを示す整数値です。慣例として、0は成功、非ゼロはエラーを示します。

変数のスコープとシャドーイング

Go言語では、変数は宣言されたブロック({} で囲まれた範囲)内で有効です。内側のブロックで外側のブロックと同じ名前の変数を宣言すると、内側のブロックでは新しい変数が優先され、外側の変数は「シャドーイング」されます。このコミットの文脈では、tooltoolName という似たような名前の変数が存在し、どちらがエラーメッセージに表示されるべきかという問題が関係しています。

技術的詳細

このコミットは、src/cmd/go/tool.go ファイル内の runTool 関数における2つの fmt.Fprintf 呼び出しを修正しています。

元のコードでは、不正なツール名が検出された場合(文字がアルファベット小文字または数字でない場合)と、ツールが存在しない場合(os.Stat がエラーを返す場合)に、エラーメッセージを標準エラー出力に書き出していました。

問題は、これらのエラーメッセージが tool という変数を参照していた点にあります。しかし、runTool 関数内で実際にユーザーが指定したツール名を処理するために使われていた変数は toolName でした。

例えば、ユーザーが go tool mytool! のように不正なツール名を指定した場合、tool 変数には予期しない値が入っている可能性があり、結果として go tool: bad tool name "" のように空文字列が表示されたり、あるいは全く関係のない値が表示されたりすることがありました。同様に、go tool nonexist のように存在しないツール名を指定した場合も、go tool: no such tool "" のように表示される可能性がありました。

この修正により、fmt.Fprintf の引数が tool から toolName に変更されました。toolName は、runTool 関数の冒頭で args[0] から取得され、ユーザーが実際にコマンドラインで指定したツール名を正確に保持しています。

// 修正前
fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", tool)
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", tool)

// 修正後
fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName)
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", toolName)

この変更により、エラーメッセージは常にユーザーが入力したツール名を正確に反映するようになり、デバッグや問題解決が容易になります。これは、Goコマンドラインツールの堅牢性とユーザーフレンドリーさを向上させるための小さな、しかし重要な修正です。

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

--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -55,7 +55,7 @@ func runTool(cmd *Command, args []string) {
 		switch {
 		case 'a' <= c && c <= 'z', '0' <= c && c <= '9':
 		default:
-			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", tool)
+			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName)
 			setExitStatus(2)
 			return
 		}
@@ -63,7 +63,7 @@ func runTool(cmd *Command, args []string) {
 	toolPath := tool(toolName)
 	// Give a nice message if there is no tool with that name.
 	if _, err := os.Stat(toolPath); err != nil {
-		fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", tool)
+		fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", toolName)
 		setExitStatus(3)
 		return
 	}

コアとなるコードの解説

この変更は、src/cmd/go/tool.go ファイル内の runTool 関数にあります。

runTool 関数は、go tool コマンドが呼び出された際に、指定されたツールを実行する主要なロジックを含んでいます。

  1. 不正なツール名のチェック (行 55-60):

    		switch {
    		case 'a' <= c && c <= 'z', '0' <= c && c <= '9':
    		default:
    			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName) // 修正箇所
    			setExitStatus(2)
    			return
    		}
    

    この部分では、ツール名の各文字が有効な文字(アルファベット小文字または数字)であるかをチェックしています。もし無効な文字が含まれていた場合、"go tool: bad tool name %q\\n" というエラーメッセージを出力します。修正前はここで tool 変数を使用していましたが、修正後は toolName を使用することで、ユーザーが入力した不正なツール名が正確にエラーメッセージに表示されるようになりました。

  2. 存在しないツールのチェック (行 63-67):

    	toolPath := tool(toolName)
    	// Give a nice message if there is no tool with that name.
    	if _, err := os.Stat(toolPath); err != nil {
    		fmt.Fprintf(os.Stderr, "go tool: no such tool %q\\n", toolName) // 修正箇所
    		setExitStatus(3)
    		return
    	}
    

    この部分では、toolName から構築された toolPath に対応する実行ファイルが実際に存在するかを os.Stat で確認しています。もしファイルが存在しない場合、"go tool: no such tool %q\\n" というエラーメッセージを出力します。ここでも同様に、修正前は tool 変数を使用していましたが、修正後は toolName を使用することで、ユーザーが指定した存在しないツール名が正確にエラーメッセージに表示されるようになりました。

この修正は、Go言語のコマンドラインツールのエラー報告の正確性を高め、ユーザーが問題をより効率的に診断できるようにするためのものです。

関連リンク

参考にした情報源リンク