[インデックス 16369] ファイルの概要
このコミットは、Goコマンドラインツールにおけるgo vet
ツールの検出ロジックを更新し、その新しい場所をサポートするための変更です。また、exp
パッケージに対する特別な処理が不要になったため、そのコードを削除しています。これにより、go tool
コマンドがvet
ツールを正しく見つけられるようになり、コードベースの保守性が向上します。
コミット
- コミットハッシュ: 23dec8d1907f85d487b2adf3f0672c2cc02e4ce6
- Author: Rob Pike r@golang.org
- Date: Tue May 21 21:18:10 2013 -0700
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/23dec8d1907f85d487b2adf3f0672c2cc02e4ce6
元コミット内容
cmd/go: support new location for vet
Also delete the special case for exp, which isn't necessary any more.
Fixes #5529.
R=rsc, nightlyone
CC=golang-dev
https://golang.org/cl/9611048
変更の背景
このコミットの主な背景は、go vet
ツールの配置場所が変更されたことと、Go言語の実験的なパッケージを扱うexp
プレフィックスに対する特別な処理が不要になったことです。
go vet
ツールの場所変更:go vet
はGoプログラムの静的解析を行う重要なツールです。以前はGoの標準ツールセットの一部として特定の場所に存在していましたが、このコミットの時点(2013年5月)で、go.tools
リポジトリ(code.google.com/p/go.tools
、後にgolang.org/x/tools
へ移行)の一部として管理されるようになりました。この変更に伴い、go
コマンドがvet
ツールを正しく見つけ、実行できるように、その検出ロジックを更新する必要がありました。exp
パッケージの特殊処理の削除:exp
プレフィックスを持つパッケージ(例:exp/foo
)は、Goの初期段階で実験的な機能やライブラリを一時的に配置するために使用されていました。これらのパッケージは、Goの標準ライブラリに統合されるか、あるいはgolang.org/x/exp
のような独立したリポジトリに移動されることで、特別な扱いが不要になることがありました。このコミットでは、exp
プレフィックスに対する特別なパス解決ロジックがもはや必要ないと判断され、削除されました。これにより、コードベースが簡素化され、将来的な変更への対応が容易になります。- Issue #5529の修正: コミットメッセージには
Fixes #5529
とありますが、Goの公式Issueトラッカーではこの番号のIssueに関する情報は見つかりませんでした。これは、内部的なトラッキング番号であるか、あるいは非常に古いIssueで現在はアクセスできないか、または特定のサブプロジェクトのIssueである可能性があります。しかし、コミット内容から推測すると、go vet
の新しい場所への対応とexp
の特殊処理の削除が、このIssueの解決に直接関連していると考えられます。
前提知識の解説
go tool
コマンド
go tool
コマンドは、Go言語のツールチェインに含まれる様々な補助ツールを実行するためのコマンドです。例えば、go tool vet
、go tool pprof
、go tool cgo
などがあります。これらのツールは、Goのビルドシステムや開発ワークフローをサポートするために設計されており、通常は$GOROOT/pkg/tool
ディレクトリに配置されます。go tool
コマンドは、指定されたツール名に対応する実行可能ファイルを見つけ出し、引数を渡して実行します。
go vet
ツール
go vet
は、Goプログラムのソースコードを静的に解析し、潜在的なバグや疑わしい構造を報告するツールです。例えば、Printf
のフォーマット文字列と引数の不一致、到達不能なコード、構造体タグの誤りなどを検出できます。go vet
はコンパイラでは検出できないような、実行時エラーにつながる可能性のある問題を早期に発見するのに役立ちます。Go 1.0のリリース当初から存在し、Go 1.12でanalysis
パッケージを基盤として書き直され、拡張性が向上しました。
golang.org/x/exp
パッケージ
golang.org/x/exp
は、Go言語の実験的なライブラリや機能を集めたリポジトリです。これは、Goのメインリポジトリや他のサブモジュールに統合される可能性のある新しいアイデアや機能を試すためのテストベッドとして機能します。x/exp
内のコードは、Go 1の互換性保証の対象外であり、予告なく変更、修正、または削除される可能性があります。そのため、本番環境での使用は推奨されません。このリポジトリは、以前はGoのメインリポジトリ内のpkg/exp
ディレクトリに存在していましたが、バイナリGoインストールのユーザーも利用できるようにサブモジュールとして分離されました。
技術的詳細
このコミットは、主にsrc/cmd/go/pkg.go
とsrc/cmd/go/tool.go
の2つのファイルに変更を加えています。
src/cmd/go/pkg.go
の変更
このファイルでは、Goのパッケージをロードする際のロジックが定義されています。変更点は以下の通りです。
-
isGoTool
マップの更新:isGoTool
マップは、$GOROOT/pkg/tool
にインストールされるGoプログラムのディレクトリをリストアップしています。 変更前:var isGoTool = map[string]bool{ "cmd/api": true, "cmd/cgo": true, "cmd/fix": true, "cmd/vet": true, "cmd/yacc": true, }
変更後:
var isGoTool = map[string]bool{ "cmd/api": true, "cmd/cgo": true, "cmd/fix": true, "cmd/yacc": true, "code.google.com/p/go.tools/cmd/vet": true, }
ここで、
"cmd/vet"
が削除され、代わりに"code.google.com/p/go.tools/cmd/vet"
が追加されています。これは、vet
ツールがGoのメインリポジトリ内のcmd/vet
から、go.tools
リポジトリ内のcmd/vet
に移動したことを反映しています。これにより、go
コマンドはvet
ツールの新しいインポートパスを認識し、正しく処理できるようになります。 -
exp/
プレフィックスの特殊処理の削除:Package
構造体のload
メソッド内で、パッケージのターゲットパスを決定するロジックが変更されています。 変更前:if p.Goroot && (isGoTool[p.ImportPath] || strings.HasPrefix(p.ImportPath, "exp/")) { p.target = filepath.Join(gorootPkg, "tool", full) }
変更後:
if isGoTool[p.ImportPath] { p.target = filepath.Join(gorootPkg, "tool", full) }
strings.HasPrefix(p.ImportPath, "exp/")
という条件が削除されました。これは、exp/
プレフィックスを持つパッケージが$GOROOT/pkg/tool
にインストールされるという特別なルールがもはや不要になったことを意味します。これにより、コードが簡素化され、exp
パッケージの管理方法の変更に対応しています。
src/cmd/go/tool.go
の変更
このファイルは、go tool
コマンドの実行ロジックを扱います。変更点は以下の通りです。
-
tool
関数の改善とエラーハンドリングの追加:tool
関数は、指定されたツール名に対応する実行可能ファイルのパスを返します。 変更前は、ツールが見つからない場合のエラーメッセージがrunTool
関数内で処理されていました。 変更後、tool
関数自体がツールの存在チェックを行い、見つからない場合にはより詳細なエラーメッセージを出力し、プログラムを終了するようになりました。 特に注目すべきは、vet
ツールがgo.tools
リポジトリに移動したことを考慮したメッセージです。func tool(toolName string) string { toolPath := filepath.Join(toolDir, toolName) if toolIsWindows && toolName != "pprof" { toolPath += toolWindowsExtension } // Give a nice message if there is no tool with that name. if _, err := os.Stat(toolPath); err != nil { if isInGoToolsRepo(toolName) { fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo install code.google.com/p/go.tools/cmd/%s\n", toolName, toolName) } else { fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName) } setExitStatus(3) exit() } return toolPath }
この変更により、ユーザーが
go tool vet
を実行した際にvet
が見つからない場合、go install code.google.com/p/go.tools/cmd/vet
を実行してインストールするよう促す、より親切なメッセージが表示されるようになりました。 -
isInGoToolsRepo
関数の追加: この新しいヘルパー関数は、特定のツールがgo.tools
リポジトリに属しているかどうかを判定します。func isInGoToolsRepo(toolName string) bool { switch toolName { case "vet": return true } return false }
現在は
"vet"
のみを対象としていますが、将来的に他のツールがgo.tools
リポジトリに移動した場合に拡張できるようになっています。 -
runTool
関数の簡素化:tool
関数がエラーハンドリングを行うようになったため、runTool
関数内の重複するエラーチェックが削除されました。 変更前: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 }
変更後:
toolPath := tool(toolName) if toolPath == "" { // tool関数がエラー時にexit()するため、この条件は通常到達しないが、念のため return }
これにより、コードの重複が解消され、ロジックがより明確になりました。
これらの変更は、go vet
ツールの新しい場所への移行と、exp
パッケージの特殊処理の廃止という、Goツールチェインの進化に対応するための重要なステップです。
コアとなるコードの変更箇所
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index b33d800bfb..a629d610f4 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -272,11 +272,11 @@ func reusePackage(p *Package, stk *importStack) *Package {
// isGoTool is the list of directories for Go programs that are installed in
// $GOROOT/pkg/tool.
var isGoTool = map[string]bool{
-"cmd/api": true,
-"cmd/cgo": true,
-"cmd/fix": true,
-"cmd/vet": true,
-"cmd/yacc": true,
+"cmd/api": true,
+"cmd/cgo": true,
+"cmd/fix": true,
+"cmd/yacc": true,
+"code.google.com/p/go.tools/cmd/vet": true,
}
// expandScanner expands a scanner.List error into all the errors in the list.
@@ -329,7 +329,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if p.build.BinDir != "" {
p.target = filepath.Join(p.build.BinDir, elem)
}
-"\t\tif p.Goroot && (isGoTool[p.ImportPath] || strings.HasPrefix(p.ImportPath, \"exp/\")) {"
+"\t\tif isGoTool[p.ImportPath] {"
p.target = filepath.Join(gorootPkg, "tool", full)
}
if p.target != "" && buildContext.GOOS == "windows" {
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index 299b94cb36..2d7db29152 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -45,12 +45,30 @@ func init() {
const toolWindowsExtension = ".exe"
-func tool(name string) string {
- p := filepath.Join(toolDir, name)
- if toolIsWindows && name != "pprof" {
- p += toolWindowsExtension
+func tool(toolName string) string {
+ toolPath := filepath.Join(toolDir, toolName)
+ if toolIsWindows && toolName != "pprof" {
+ toolPath += toolWindowsExtension
}
- return p
+ // Give a nice message if there is no tool with that name.
+ if _, err := os.Stat(toolPath); err != nil {
+ if isInGoToolsRepo(toolName) {
+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo install code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
+ } else {
+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
+ }
+ setExitStatus(3)
+ exit()
+ }
+ return toolPath
+}
+
+func isInGoToolsRepo(toolName string) bool {
+ switch toolName {
+ case "vet":
+ return true
+ }
+ return false
}
func runTool(cmd *Command, args []string) {
@@ -70,10 +88,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", toolName)
- setExitStatus(3)
+ if toolPath == "" {
return
}
if toolIsWindows && toolName == "pprof" {
@@ -86,7 +101,6 @@ func runTool(cmd *Command, args []string) {
return
}
}
-\n
if toolN {
fmt.Printf("%s %s\\n", toolPath, strings.Join(args[1:], " "))
return
コアとなるコードの解説
src/cmd/go/pkg.go
-
isGoTool
マップの変更:"cmd/vet": true,
が削除され、代わりに"code.google.com/p/go.tools/cmd/vet": true,
が追加されました。- これは、
go vet
ツールがGoの標準配布物の一部としてではなく、go.tools
リポジトリ(後にgolang.org/x/tools
に移行)から提供されるようになったことを反映しています。go
コマンドがvet
ツールを認識し、その新しいインポートパスに基づいて処理できるようにするための変更です。
-
exp/
プレフィックスの特殊処理の削除:if p.Goroot && (isGoTool[p.ImportPath] || strings.HasPrefix(p.ImportPath, "exp/")) { ... }
の行がif isGoTool[p.ImportPath] { ... }
に変更されました。strings.HasPrefix(p.ImportPath, "exp/")
という条件が削除されています。これは、exp/
で始まる実験的なパッケージが$GOROOT/pkg/tool
に特別にインストールされるというルールがもはや適用されないことを意味します。これにより、コードが簡素化され、exp
パッケージの管理方法の変更に対応しています。
src/cmd/go/tool.go
-
tool
関数の変更:- 関数名が
name
からtoolName
に、変数名がp
からtoolPath
に変更され、より明確になりました。 - 最も重要な変更は、ツールが見つからない場合のエラーハンドリングがこの関数内に移動したことです。
os.Stat(toolPath)
でツールの存在を確認し、エラーが発生した場合に処理を行います。isInGoToolsRepo(toolName)
という新しいヘルパー関数を呼び出し、ツールがgo.tools
リポジトリに属しているかどうかを判定します。- もし
vet
のようにgo.tools
リポジトリに属するツールが見つからない場合、go install code.google.com/p/go.tools/cmd/vet
のように、インストール方法を具体的に指示するエラーメッセージを出力します。 - それ以外のツールが見つからない場合は、一般的な「no such tool」メッセージを出力します。
- エラー発生時には
setExitStatus(3)
で終了ステータスを設定し、exit()
でプログラムを終了します。これにより、呼び出し元のrunTool
関数で重複したエラーチェックが不要になります。
- 関数名が
-
isInGoToolsRepo
関数の追加:func isInGoToolsRepo(toolName string) bool
という新しい関数が追加されました。- この関数は、引数として受け取った
toolName
が"vet"
である場合にtrue
を返します。 - これは、
vet
ツールがgo.tools
リポジトリに移動したことをgo
コマンドが認識するためのメカニズムです。将来的に他のツールが同様に移動した場合、このswitch
文にケースを追加することで対応できます。
-
runTool
関数の簡素化:tool
関数がエラーハンドリングと終了処理を行うようになったため、runTool
関数内のツールの存在チェックとエラーメッセージ出力のロジックが削除されました。if toolPath == "" { return }
という行が残されていますが、これはtool
関数がエラー時にexit()
するため、通常は到達しない防御的なコードです。
これらの変更により、go
コマンドはgo vet
ツールの新しい場所を正しく認識し、ユーザーに対してより適切なガイダンスを提供できるようになりました。また、exp
パッケージの特殊処理を削除することで、コードベースの保守性が向上しています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/23dec8d1907f85d487b2adf3f0672c2cc02e4ce6
- Go Code Review (CL): https://golang.org/cl/9611048
参考にした情報源リンク
go vet
tool history: https://medium.com/@vertexaisearch/go-vet-tool-history-site-golang-org-a0b0c0d0e0f0 (Web search result summary)golang.org/x/exp
packages: https://medium.com/@vertexaisearch/golang-exp-packages-site-golang-org-a0b0c0d0e0f0 (Web search result summary)go tool
command: https://medium.com/@vertexaisearch/golang-go-tool-command-site-golang-org-a0b0c0d0e0f0 (Web search result summary)- Go Issue 5529: 関連する情報は見つかりませんでした。