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

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

このコミットは、Go言語のコマンドラインツール cmd/go における vet コマンドの挙動を修正するものです。具体的には、vet ツールが型チェックを行うようになったことに伴い、チェック対象のファイルセットを pkg.allgofiles から pkg.gofiles に変更することで、無視されるべきファイルが誤ってチェックされる問題を解決しています。

コミット

commit f5afc7d44f5ef20316c9d1d7ec28b45117f3add3
Author: Francisco Souza <franciscossouza@gmail.com>
Date:   Mon Feb 25 10:43:04 2013 -0800

    cmd/go: fix vet
    
    Now that vet does typechecking, it should use only pkg.gofiles, instead
    of pkg.allgofiles. Ignored files should not be checked by vet, because
    they wouldn't typecheck.
    
    Fixes #4906.
    
    R=rsc, r
    CC=golang-dev
    https://golang.org/cl/7401051

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

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

元コミット内容

cmd/go: fix vet

vet が型チェックを行うようになったため、pkg.allgofiles の代わりに pkg.gofiles のみを使用すべきです。無視されたファイルは vet によってチェックされるべきではありません。なぜなら、それらは型チェックに合格しないからです。

Fixes #4906.

変更の背景

このコミットの背景には、Go言語の静的解析ツールである go vet の機能拡張があります。元々 go vet は、Goのソースコードにおける疑わしい構造や潜在的なエラーを検出するためのツールでしたが、このコミットが作成された時期(2013年2月頃)に、go vet がより高度な解析を行うために「型チェック」の機能を取り込むようになりました。

型チェック機能が導入される前は、go vet はファイルの構文解析に基づいて動作することが多く、Goコンパイラが無視するようなファイル(例えば、ビルドタグによって特定の環境でのみコンパイルされるファイルや、テストファイルではないがパッケージに含まれる補助的なファイルなど)も解析対象に含める pkg.allgofiles を使用しても問題が少なかったと考えられます。

しかし、go vet が型チェックを行うようになると、コンパイル対象ではないファイル(例えば、特定のOSやアーキテクチャ向けに書かれたが現在のビルド環境では無視されるファイル、あるいは意図的に不完全な状態のコードスニペットなど)を pkg.allgofiles を通じてチェックしようとすると、それらのファイルが型チェックに失敗し、不必要なエラーや警告を発生させる問題が生じました。これは、開発者が実際にコンパイルして使用するコードではない部分で vet がエラーを出すため、ノイズとなり、本来修正すべき問題を見落とす原因にもなりかねません。

この問題は、GoのIssueトラッカーで #4906 として報告されており、このコミットはその問題を解決するために作成されました。開発ワークフローにおいて、go vet はクリーンなコードベースを維持するために重要なツールであるため、その出力が正確で、かつ開発者の意図に沿ったものであることが求められます。この変更は、go vet の実用性と信頼性を向上させるための重要な修正と言えます。

前提知識の解説

このコミットを理解するためには、以下のGo言語および関連ツールの概念を理解しておく必要があります。

  1. go vet: go vet は、Go言語のソースコードを静的に解析し、潜在的なバグや疑わしい構造を報告するツールです。例えば、Printf のフォーマット文字列と引数の不一致、到達不能なコード、ロックの誤用などを検出します。このツールは、コンパイラが検出できないが実行時に問題を引き起こす可能性のあるコードパターンを見つけるのに役立ちます。このコミットの時点では、vet は型チェック機能を取り込み、より深いレベルでのコード解析が可能になっていました。

  2. Goパッケージのビルドプロセスとファイルの種類: Goのビルドシステムは、ソースファイルの種類を区別します。

    • .go ファイル: Goのソースコードファイルです。
    • ビルドタグ (Build Tags): Goのソースファイルには、// +build linux darwin のようなビルドタグを含めることができます。これにより、特定のOSやアーキテクチャ、またはカスタムタグが指定された場合にのみ、そのファイルがコンパイル対象に含まれるようになります。ビルドタグに一致しないファイルは、コンパイラによって完全に無視されます。
    • テストファイル (_test.go): ファイル名が _test.go で終わるファイルは、テストコードとして扱われます。これらは通常のビルドプロセスではコンパイルされず、go test コマンドが実行されたときにのみコンパイル・実行されます。
  3. pkg.gofilespkg.allgofiles: Goの内部ビルドシステムやツールがパッケージ内のソースファイルを扱う際に使用する概念です。

    • pkg.gofiles: これは、現在のビルド環境(OS、アーキテクチャ、ビルドタグなど)に基づいて、実際にコンパイルされるGoのソースファイル(.go ファイル)のリストを指します。これには、ビルドタグによって無視されるファイルや、_test.go ファイルは含まれません。つまり、コンパイラが実際に処理するファイルのセットです。
    • pkg.allgofiles: これは、パッケージディレクトリ内に存在するすべてのGoのソースファイル(.go ファイル)のリストを指します。これには、ビルドタグによって無視されるファイルや、_test.go ファイルも含まれる可能性があります。つまり、ディレクトリ内のすべてのGoソースファイルの包括的なリストです。

このコミットの核心は、go vet が型チェックを行うようになったことで、コンパイラが無視するファイル(pkg.allgofiles には含まれるが pkg.gofiles には含まれないファイル)を vet がチェックしようとすると、それらのファイルは型チェックの前提となるコンパイル環境に存在しないため、型エラーが発生するという問題です。vet はコンパイラと同様に、実際にビルドされるコードに対してのみ実行されるべきである、という原則に基づいています。

技術的詳細

このコミットの技術的な詳細は、go vet が静的解析を行う際の「コンテキスト」の重要性に集約されます。

go vet が型チェックを行うということは、単に構文的なパターンを検出するだけでなく、Goコンパイラがコードを解釈するのと同様に、型情報、スコープ、インポートされたパッケージの定義などを考慮してコードの正当性を検証するようになったことを意味します。

従来の go vetpkg.allgofiles を使用していたのは、おそらく、その時点での vet の解析が、個々のファイルの構文レベルでのチェックが主であり、ファイルがコンパイル可能であるかどうかの厳密な検証を必要としなかったためです。例えば、Printf のフォーマット文字列のチェックなどは、そのファイルが実際にコンパイルされるかどうかに関わらず、構文的に有効なGoファイルであれば実行可能でした。

しかし、型チェックが導入されると状況は一変します。型チェックは、コードがGo言語の型システムに準拠しているかを検証するプロセスであり、これには以下の要素が不可欠です。

  1. 完全な型情報: 変数、関数、構造体などの型が正確に解決されている必要があります。これは、インポートされたパッケージの定義や、同じパッケージ内の他のファイルの定義に依存します。
  2. コンパイル可能な状態: 型チェックは、コードがコンパイル可能であることを前提とします。もしファイルがビルドタグによって現在の環境でコンパイル対象から外されている場合、そのファイルはコンパイラによって処理されず、結果として型情報が不完全または存在しない状態になります。

pkg.allgofiles には、ビルドタグによって現在のビルド環境ではコンパイルされないファイルが含まれる可能性があります。これらのファイルは、コンパイラが無視するため、それらのファイル内のコードは型解決されません。go vet がこれらの「無視されたファイル」に対して型チェックを実行しようとすると、型情報が欠落しているため、本来エラーではないコードに対しても型エラーを報告してしまいます。これは、vet の出力に誤った情報(ノイズ)を混入させ、開発者が本当に修正すべき問題を見つけにくくします。

この問題を解決するために、go vetpkg.gofiles を使用するように変更されました。pkg.gofiles は、現在のビルド環境で実際にコンパイルされるGoソースファイルのセットを正確に表します。これにより、go vet はコンパイラが処理するのと同じコードセットに対して型チェックを実行するため、vet の出力はより正確で、開発者の意図に沿ったものになります。つまり、vet は「実際にビルドされるコード」に対してのみ警告を出すようになり、開発者はその警告に集中できるようになります。

この変更は、Goツールの設計哲学である「ツールはコンパイラと協調して動作し、開発者に有用な情報のみを提供するべきである」という原則に合致しています。

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

変更は src/cmd/go/vet.go ファイルの1箇所のみです。

--- a/src/cmd/go/vet.go
+++ b/src/cmd/go/vet.go
@@ -32,6 +32,6 @@ func runVet(cmd *Command, args []string) {
 		// Use pkg.gofiles instead of pkg.Dir so that
 		// the command only applies to this package,
 		// not to packages in subdirectories.
-		run(tool("vet"), relPaths(pkg.allgofiles))
+		run(tool("vet"), relPaths(pkg.gofiles))
 	}
 }

コアとなるコードの解説

変更された行は src/cmd/go/vet.go 内の runVet 関数の一部です。

元のコード:

run(tool("vet"), relPaths(pkg.allgofiles))

変更後のコード:

run(tool("vet"), relPaths(pkg.gofiles))

この変更は、go vet ツールを実行する際に、引数として渡すファイルのリストを pkg.allgofiles から pkg.gofiles に切り替えるものです。

  • tool("vet"): これは go vet 実行可能ファイルのパスを取得するヘルパー関数です。
  • relPaths(...): これは、与えられたファイルパスのリストを、現在の作業ディレクトリからの相対パスに変換するヘルパー関数です。
  • pkg.allgofiles: 変更前は、パッケージ内のすべてのGoソースファイル(ビルドタグで無視されるファイルやテストファイルも含む可能性のある包括的なリスト)が vet に渡されていました。
  • pkg.gofiles: 変更後は、現在のビルド環境で実際にコンパイルされるGoソースファイルのみが vet に渡されます。

この一行の変更がもたらす影響は非常に大きく、go vet が型チェックを行うようになったという前提と合わせて考えると、以下のようになります。

  1. 正確性の向上: vet は、実際にコンパイルされるコードに対してのみ型チェックを行うようになります。これにより、ビルドタグによって無視されるファイルや、現在の環境ではコンパイルされないファイルに起因する誤った型エラーや警告が排除されます。
  2. ノイズの削減: 開発者は、実際にビルドされるコードに関する vet の警告に集中できるようになり、開発ワークフローの効率が向上します。
  3. コンパイラとの整合性: vet の動作がGoコンパイラの動作とより密接に連携するようになります。コンパイラが無視するファイルは vet も無視する、という一貫した挙動が実現されます。

この修正は、go vet がより強力な解析能力(型チェック)を獲得したことに伴い、その解析対象を適切に限定することで、ツールの有用性と信頼性を最大限に引き出すための、まさに「修正」と呼ぶにふさわしい変更です。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント(go vet、ビルドタグ、パッケージ構造に関する情報)
  • Go言語のIssueトラッカー(特にIssue #4906の議論)
  • Go言語のソースコード(cmd/go および go/build パッケージの関連部分)
  • Go言語に関する技術ブログや解説記事(go vet の機能や進化に関するもの)

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

このコミットは、Go言語のコマンドラインツール cmd/go における vet コマンドの挙動を修正するものです。具体的には、vet ツールがより高度な型関連のチェックを行うようになったことに伴い、チェック対象のファイルセットを pkg.allgofiles から pkg.gofiles に変更することで、無視されるべきファイルが誤ってチェックされる問題を解決しています。

コミット

commit f5afc7d44f5ef20316c9d1d7ec28b45117f3add3
Author: Francisco Souza <franciscossouza@gmail.com>
Date:   Mon Feb 25 10:43:04 2013 -0800

    cmd/go: fix vet
    
    Now that vet does typechecking, it should use only pkg.gofiles, instead
    of pkg.allgofiles. Ignored files should not be checked by vet, because
    they wouldn't typecheck.
    
    Fixes #4906.
    
    R=rsc, r
    CC=golang-dev
    https://golang.org/cl/7401051

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

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

元コミット内容

cmd/go: fix vet

vet が型チェックを行うようになったため、pkg.allgofiles の代わりに pkg.gofiles のみを使用すべきです。無視されたファイルは vet によってチェックされるべきではありません。なぜなら、それらは型チェックに合格しないからです。

Fixes #4906.

変更の背景

このコミットの背景には、Go言語の静的解析ツールである go vet の機能拡張があります。元々 go vet は、Goのソースコードにおける疑わしい構造や潜在的なエラーを検出するためのツールでしたが、このコミットが作成された時期(2013年2月頃)に、go vet がより高度な解析を行うために「型チェック」の側面を取り込むようになりました。これは、Printf のフォーマット文字列と引数の不一致を検証するなど、型情報に基づいたより深い分析を可能にするものでした。

型関連のチェック機能が導入される前は、go vet はファイルの構文解析に基づいて動作することが多く、Goコンパイラが無視するようなファイル(例えば、ビルドタグによって特定の環境でのみコンパイルされるファイルや、テストファイルではないがパッケージに含まれる補助的なファイルなど)も解析対象に含める pkg.allgofiles を使用しても問題が少なかったと考えられます。

しかし、go vet が型関連のチェックを強化するようになると、コンパイル対象ではないファイル(例えば、特定のOSやアーキテクチャ向けに書かれたが現在のビルド環境では無視されるファイル、あるいは意図的に不完全な状態のコードスニペットなど)を pkg.allgofiles を通じてチェックしようとすると、それらのファイルは型チェックの前提となるコンパイル環境に存在しないため、不必要なエラーや警告を発生させる問題が生じました。これは、開発者が実際にコンパイルして使用するコードではない部分で vet がエラーを出すため、ノイズとなり、本来修正すべき問題を見落とす原因にもなりかねません。

この問題は、GoのIssueトラッカーで #4906 として報告されており、このコミットはその問題を解決するために作成されました。開発ワークフローにおいて、go vet はクリーンなコードベースを維持するために重要なツールであるため、その出力が正確で、かつ開発者の意図に沿ったものであることが求められます。この変更は、go vet の実用性と信頼性を向上させるための重要な修正と言えます。

前提知識の解説

このコミットを理解するためには、以下のGo言語および関連ツールの概念を理解しておく必要があります。

  1. go vet: go vet は、Go言語のソースコードを静的に解析し、潜在的なバグや疑わしい構造を報告するツールです。例えば、Printf のフォーマット文字列と引数の不一致、到達不能なコード、ロックの誤用などを検出します。このツールは、コンパイラが検出できないが実行時に問題を引き起こす可能性のあるコードパターンを見つけるのに役立ちます。このコミットの時点では、vet は型情報に基づいたより深い解析が可能になっていました。

  2. Goパッケージのビルドプロセスとファイルの種類: Goのビルドシステムは、ソースファイルの種類を区別します。

    • .go ファイル: Goのソースコードファイルです。
    • ビルドタグ (Build Tags): Goのソースファイルには、// +build linux darwin のようなビルドタグを含めることができます。これにより、特定のOSやアーキテクチャ、またはカスタムタグが指定された場合にのみ、そのファイルがコンパイル対象に含まれるようになります。ビルドタグに一致しないファイルは、コンパイラによって完全に無視されます。
    • テストファイル (_test.go): ファイル名が _test.go で終わるファイルは、テストコードとして扱われます。これらは通常のビルドプロセスではコンパイルされず、go test コマンドが実行されたときにのみコンパイル・実行されます。
  3. pkg.gofilespkg.allgofiles: Goの内部ビルドシステムやツールがパッケージ内のソースファイルを扱う際に使用する概念です。

    • pkg.gofiles: これは、現在のビルド環境(OS、アーキテクチャ、ビルドタグなど)に基づいて、実際にコンパイルされるGoのソースファイル(.go ファイル)のリストを指します。これには、ビルドタグによって無視されるファイルや、_test.go ファイルは含まれません。つまり、コンパイラが実際に処理するファイルのセットです。
    • pkg.allgofiles: これは、パッケージディレクトリ内に存在するすべてのGoのソースファイル(.go ファイル)のリストを指します。これには、ビルドタグによって無視されるファイルや、_test.go ファイルも含まれる可能性があります。つまり、ディレクトリ内のすべてのGoソースファイルの包括的なリストです。

このコミットの核心は、go vet が型関連のチェックを行うようになったことで、コンパイラが無視するファイル(pkg.allgofiles には含まれるが pkg.gofiles には含まれないファイル)を vet がチェックしようとすると、それらのファイルは型チェックの前提となるコンパイル環境に存在しないため、型エラーが発生するという問題です。vet はコンパイラと同様に、実際にビルドされるコードに対してのみ実行されるべきである、という原則に基づいています。

技術的詳細

このコミットの技術的な詳細は、go vet が静的解析を行う際の「コンテキスト」の重要性に集約されます。

go vet が型関連のチェックを行うということは、単に構文的なパターンを検出するだけでなく、Goコンパイラがコードを解釈するのと同様に、型情報、スコープ、インポートされたパッケージの定義などを考慮してコードの正当性を検証するようになったことを意味します。このコミットが作成された2013年2月時点では、go/types パッケージのような完全な型チェッカーがGoの標準ライブラリに導入される前(go/types はGo 1.5で導入)でしたが、vet は既に Printf のフォーマット文字列の検証など、型情報に依存する高度なチェックを実行していました。

従来の go vetpkg.allgofiles を使用していたのは、おそらく、その時点での vet の解析が、個々のファイルの構文レベルでのチェックが主であり、ファイルがコンパイル可能であるかどうかの厳密な検証を必要としなかったためです。例えば、Printf のフォーマット文字列のチェックなどは、そのファイルが実際にコンパイルされるかどうかに関わらず、構文的に有効なGoファイルであれば実行可能でした。

しかし、型関連のチェックが強化されると状況は一変します。型関連のチェックは、コードがGo言語の型システムに準拠しているかを検証するプロセスであり、これには以下の要素が不可欠です。

  1. 完全な型情報: 変数、関数、構造体などの型が正確に解決されている必要があります。これは、インポートされたパッケージの定義や、同じパッケージ内の他のファイルの定義に依存します。
  2. コンパイル可能な状態: 型関連のチェックは、コードがコンパイル可能であることを前提とします。もしファイルがビルドタグによって現在の環境でコンパイル対象から外されている場合、そのファイルはコンパイラによって処理されず、結果として型情報が不完全または存在しない状態になります。

pkg.allgofiles には、ビルドタグによって現在のビルド環境ではコンパイルされないファイルが含まれる可能性があります。これらのファイルは、コンパイラが無視するため、それらのファイル内のコードは型解決されません。go vet がこれらの「無視されたファイル」に対して型関連のチェックを実行しようとすると、型情報が欠落しているため、本来エラーではないコードに対しても型エラーを報告してしまいます。これは、vet の出力に誤った情報(ノイズ)を混入させ、開発者が本当に修正すべき問題を見つけにくくします。

この問題を解決するために、go vetpkg.gofiles を使用するように変更されました。pkg.gofiles は、現在のビルド環境で実際にコンパイルされるGoソースファイルのセットを正確に表します。これにより、go vet はコンパイラが処理するのと同じコードセットに対して型関連のチェックを実行するため、vet の出力はより正確で、開発者の意図に沿ったものになります。つまり、vet は「実際にビルドされるコード」に対してのみ警告を出すようになり、開発者はその警告に集中できるようになります。

この変更は、Goツールの設計哲学である「ツールはコンパイラと協調して動作し、開発者に有用な情報のみを提供するべきである」という原則に合致しています。

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

変更は src/cmd/go/vet.go ファイルの1箇所のみです。

--- a/src/cmd/go/vet.go
+++ b/cmd/go/vet.go
@@ -32,6 +32,6 @@ func runVet(cmd *Command, args []string) {
 		// Use pkg.gofiles instead of pkg.Dir so that
 		// the command only applies to this package,
 		// not to packages in subdirectories.
-		run(tool("vet"), relPaths(pkg.allgofiles))
+		run(tool("vet"), relPaths(pkg.gofiles))
 	}
 }

コアとなるコードの解説

変更された行は src/cmd/go/vet.go 内の runVet 関数の一部です。

元のコード:

run(tool("vet"), relPaths(pkg.allgofiles))

変更後のコード:

run(tool("vet"), relPaths(pkg.gofiles))

この変更は、go vet ツールを実行する際に、引数として渡すファイルのリストを pkg.allgofiles から pkg.gofiles に切り替えるものです。

  • tool("vet"): これは go vet 実行可能ファイルのパスを取得するヘルパー関数です。
  • relPaths(...): これは、与えられたファイルパスのリストを、現在の作業ディレクトリからの相対パスに変換するヘルパー関数です。
  • pkg.allgofiles: 変更前は、パッケージ内のすべてのGoソースファイル(ビルドタグで無視されるファイルやテストファイルも含む可能性のある包括的なリスト)が vet に渡されていました。
  • pkg.gofiles: 変更後は、現在のビルド環境で実際にコンパイルされるGoソースファイルのみが vet に渡されます。

この一行の変更がもたらす影響は非常に大きく、go vet が型関連のチェックを行うようになったという前提と合わせて考えると、以下のようになります。

  1. 正確性の向上: vet は、実際にコンパイルされるコードに対してのみ型関連のチェックを行うようになります。これにより、ビルドタグによって無視されるファイルや、現在の環境ではコンパイルされないファイルに起因する誤った型エラーや警告が排除されます。
  2. ノイズの削減: 開発者は、実際にビルドされるコードに関する vet の警告に集中できるようになり、開発ワークフローの効率が向上します。
  3. コンパイラとの整合性: vet の動作がGoコンパイラの動作とより密接に連携するようになります。コンパイラが無視するファイルは vet も無視する、という一貫した挙動が実現されます。

この修正は、go vet がより強力な解析能力(型関連のチェック)を獲得したことに伴い、その解析対象を適切に限定することで、ツールの有用性と信頼性を最大限に引き出すための、まさに「修正」と呼ぶにふさわしい変更です。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント(go vet、ビルドタグ、パッケージ構造に関する情報)
  • Go言語のIssueトラッカー(特にIssue #4906の議論)
  • Go言語のソースコード(cmd/go および go/build パッケージの関連部分)
  • Go言語に関する技術ブログや解説記事(go vet の機能や進化に関するもの)
  • Web検索: "Go vet typechecking introduction date" (2013年2月時点での vet の型関連チェックの状況を把握するため)