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

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

このコミットは、Go言語のコマンドラインツールgoにおけるlistサブコマンドに-raceフラグを追加するものです。これにより、go listがパッケージの依存関係を列挙する際に、Goのデータ競合検出器(Race Detector)が必要とする依存関係も考慮に入れるようになります。

コミット

commit d595b67a12f1ecc0839bc4ced7efae916ed5584d
Author: Rob Pike <r@golang.org>
Date:   Thu Aug 29 11:16:53 2013 +1000

    cmd/go: add -race flag to 'go list'
    
    Causes the package dependencies to include those for race detection.
    Fixes #5653.
    
    R=golang-dev, dave, bradfitz
    CC=golang-dev
    https://golang.org/cl/13236045

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

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

元コミット内容

cmd/go: add -race flag to 'go list'

この変更は、go listコマンドに-raceフラグを追加します。このフラグは、パッケージの依存関係にデータ競合検出に必要なものが含まれるようにします。Issue #5653を修正します。

変更の背景

Go言語には、並行処理におけるデータ競合(data race)を検出するための強力なツールである「Race Detector」が組み込まれています。通常、go build -racego test -raceのように、ビルド時やテスト時に-raceフラグを指定することでRace Detectorが有効になります。Race Detectorを有効にすると、Goツールチェインは、競合検出に必要な追加のランタイムライブラリやインストゥルメンテーションコードをコンパイルされたバイナリに含めます。

go listコマンドは、Goパッケージに関する情報を表示するために使用されます。これには、パッケージのインポートパス、依存関係、ビルドタグなどが含まれます。しかし、Race Detectorを有効にした場合のビルドプロセスでは、通常のビルドとは異なる依存関係(例えば、runtime/raceパッケージなど)が必要になります。

このコミット以前は、go listがRace Detectorのコンテキストでビルドされるパッケージの正確な依存関係を反映していませんでした。これは、Race Detectorを有効にしたビルド環境で、go listが返す情報と実際のビルド結果との間に不整合が生じる可能性を意味します。例えば、CI/CDパイプラインでRace Detectorを有効にしてビルドを行う際に、go listで依存関係を事前に確認しようとしても、その情報が不正確である可能性がありました。

この変更の背景には、go listが提供する情報の一貫性と正確性を向上させ、特にRace Detectorを使用する開発者やツールが、より信頼性の高いパッケージ情報を取得できるようにするという目的があります。コミットメッセージにあるFixes #5653は、この問題がGoのIssueトラッカーで報告され、修正が求められていたことを示唆しています。ただし、GoのIssue #5653は現在公開されている情報源では確認できませんでした。

前提知識の解説

Go言語のパッケージと依存関係

Go言語のプロジェクトは、パッケージ(package)という単位で構成されます。各パッケージは、他のパッケージをimportすることでその機能を利用できます。Goツールチェインは、これらのインポート宣言を解析し、必要な依存関係を解決して実行可能なバイナリを生成します。

Goのビルドタグ(Build Tags)

Goでは、ソースコードファイルにビルドタグ(// +build tag)を記述することで、特定の条件に基づいてファイルのコンパイルを制御できます。例えば、オペレーティングシステムやアーキテクチャ、あるいはカスタムのタグに基づいて、特定のファイルをビルドに含めたり除外したりできます。go build -tags 'tag1 tag2'のようにコマンドラインでタグを指定することで、これらの条件を有効にできます。

Goのデータ競合検出器(Race Detector)

GoのRace Detectorは、並行処理におけるデータ競合を検出するための動的解析ツールです。データ競合は、複数のGoroutineが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みであり、かつそれらのアクセスが同期メカニズムによって保護されていない場合に発生します。データ競合は、プログラムの予測不能な動作やクラッシュの原因となることがあり、デバッグが非常に困難です。

Race Detectorは、プログラムの実行中にメモリアクセスを監視し、競合のパターンを検出すると警告を出力します。これを有効にするには、go build -racego test -raceのように-raceフラグをGoコマンドに渡します。このフラグが指定されると、Goコンパイラとランタイムは、競合検出に必要な追加のコード(インストゥルメンテーション)を生成し、実行時にメモリアクセスを追跡します。このインストゥルメンテーションは、プログラムの実行速度を低下させる可能性がありますが、競合の特定には非常に有効です。

Race Detectorが有効になると、runtime/raceパッケージなど、競合検出に必要な特別なパッケージが依存関係として追加されます。これらのパッケージは、通常のビルドでは含まれません。

技術的詳細

このコミットの技術的な核心は、go listコマンドがパッケージ情報を収集する際に、Race Detectorが有効な場合のビルドコンテキストを考慮に入れるようにすることです。

go listコマンドは、内部的にGoのビルドシステムと同じロジックを使用してパッケージの依存関係を解決します。これには、ビルドタグの評価や、特定のビルドモード(例えば、Race Detectorが有効な場合)に応じた依存関係の調整が含まれます。

変更前は、go listはRace Detectorが有効な場合の特別な依存関係(runtime/raceなど)を認識していませんでした。そのため、go listが返すパッケージ情報には、Race Detectorを有効にした場合に実際にビルドされる依存関係が反映されていませんでした。

このコミットでは、go listコマンドに-raceフラグが追加され、このフラグが指定された場合、内部的にbuildRaceというグローバルなビルド設定フラグがtrueに設定されます。このbuildRaceフラグは、Goツールチェインのビルドロジック全体で参照され、Race Detectorに必要な依存関係(例: runtime/raceパッケージ)がビルドグラフに適切に追加されるようにします。

具体的には、go listの実行時に-raceフラグが渡されると、cmd/go/list.go内のrunList関数がbuildRace = trueを設定します。このbuildRace変数は、Goツールチェインの他の部分(例えば、パッケージのロードや依存関係の解決を行うコード)で利用され、Race Detectorが有効な場合のビルドコンテキストをシミュレートします。これにより、go listは、Race Detectorが有効な場合に実際にコンパイルされるパッケージとその依存関係を正確に報告できるようになります。

この変更は、go listの出力が、特定のビルド設定(この場合はRace Detectorの有効化)における実際のビルドプロセスをより正確に反映するようにするためのものです。これにより、開発者は、Race Detectorを有効にした場合の依存関係を事前に確認したり、CI/CDシステムでビルドの整合性を検証したりする際に、より信頼性の高い情報を得られるようになります。

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

変更はsrc/cmd/go/list.goファイルに対して行われています。

diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
index 6b729aaec4..f56ebed382 100644
--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -14,7 +14,7 @@ import (
 )
 
 var cmdList = &Command{
-	UsageLine: "list [-e] [-f format] [-json] [-tags 'tag list'] [packages]",
+	UsageLine: "list [-e] [-race] [-f format] [-json] [-tags 'tag list'] [packages]",
 	Short:     "list packages",
 	Long: `
 List lists the packages named by the import paths, one per line.
@@ -91,6 +91,9 @@ a non-nil Error field; other information may or may not be missing
 The -tags flag specifies a list of build tags, like in the 'go build'
 command.
 
+The -race flag causes the package data to include the dependencies
+required by the race detector.
+
 For more about specifying packages, see 'go help packages'.
 	`,
 }
@@ -104,12 +107,17 @@ func init() {
 var listE = cmdList.Flag.Bool("e", false, "")
 var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
 var listJson = cmdList.Flag.Bool("json", false, "")
+var listRace = cmdList.Flag.Bool("race", false, "")
 var nl = []byte{'\n'}
 
 func runList(cmd *Command, args []string) {
 	out := newTrackingWriter(os.Stdout)
 	defer out.w.Flush()
 
+	if *listRace {
+		buildRace = true
+	}
+
 	var do func(*Package)
 	if *listJson {
 		do = func(p *Package) {

コアとなるコードの解説

  1. UsageLineの変更: cmdList構造体のUsageLineフィールドが更新され、listコマンドのヘルプメッセージに-raceフラグが追加されました。

    -	UsageLine: "list [-e] [-f format] [-json] [-tags 'tag list'] [packages]",
    +	UsageLine: "list [-e] [-race] [-f format] [-json] [-tags 'tag list'] [packages]",
    

    これにより、ユーザーはgo help listを実行した際に、-raceフラグが利用可能であることを認識できます。

  2. Long説明の追加: cmdList構造体のLongフィールドに、-raceフラグに関する説明が追加されました。

    +The -race flag causes the package data to include the dependencies
    +required by the race detector.
    

    これは、-raceフラグが何をするのかを簡潔に説明しています。

  3. -raceフラグの定義: init()関数内で、listRaceという新しいブール型フラグが定義されました。これは、コマンドラインで-raceフラグが指定されたかどうかを捕捉します。

    var listRace = cmdList.Flag.Bool("race", false, "")
    

    cmdList.Flag.Bool("race", false, "")は、go listコマンドに-raceという名前のブール型フラグを追加し、デフォルト値をfalseに設定します。

  4. buildRaceグローバル変数の設定: runList関数内で、listRaceフラグがtrueの場合(つまり、ユーザーが-raceを指定した場合)に、グローバル変数buildRacetrueに設定するロジックが追加されました。

    func runList(cmd *Command, args []string) {
    	out := newTrackingWriter(os.Stdout)
    	defer out.w.Flush()
    
    	if *listRace {
    		buildRace = true
    	}
    
    	var do func(*Package)
    	if *listJson {
    		do = func(p *Package) {
    

    buildRaceは、Goツールチェイン全体で共有されるビルド設定フラグであり、Race Detectorが有効なビルドコンテキストを示すために使用されます。このフラグがtrueに設定されることで、go listの内部的なパッケージ解決ロジックが、Race Detectorに必要な追加の依存関係を考慮に入れるようになります。これにより、go listは、Race Detectorが有効な場合の正確なパッケージ情報を提供できるようになります。

この変更は、go listコマンドの機能性を拡張し、GoのビルドシステムにおけるRace Detectorのサポートをより一貫性のあるものにするための重要なステップです。

関連リンク

  • Go言語公式ウェブサイト: https://golang.org/
  • Go Race Detectorに関する公式ドキュメント: https://go.dev/doc/articles/race_detector (これは現在のドキュメントであり、コミット当時のものとは異なる可能性がありますが、Race Detectorの概念を理解するのに役立ちます。)

参考にした情報源リンク

  • コミットハッシュ: d595b67a12f1ecc0839bc4ced7efae916ed5584d
  • GitHubコミットページ: https://github.com/golang/go/commit/d595b67a12f1ecc0839bc4ced7efae916ed5584d
  • Go Issue #5653 (検索しましたが、公式な情報源では見つかりませんでした。古いIssueであるか、番号が変更された可能性があります。)
  • Go言語のビルドタグに関する情報 (一般的なGoのドキュメントやチュートリアルで確認できます。)
  • Go言語のパッケージ管理と依存関係に関する情報 (一般的なGoのドキュメントやチュートリアルで確認できます。)
  • Go Race Detectorの動作原理に関する情報 (一般的なGoのドキュメントやブログ記事で確認できます。)