[インデックス 17483] ファイルの概要
このコミットは、Go言語のツールチェインの一部である cmd/api
コマンドの挙動を変更するものです。cmd/api
は、Goの標準ライブラリの公開APIをチェックし、その変更を追跡するために使用されます。この変更により、定数(const
)の値がAPIの出力に含まれるようになります。
具体的には、以下のファイルが変更されています。
src/cmd/api/goapi.go
:cmd/api
コマンドの主要なロジックが含まれるGoソースファイルです。定数の出力方法が修正されています。src/cmd/api/testdata/src/pkg/p1/golden.txt
:cmd/api
のテストデータであり、期待されるAPI出力の「ゴールデンファイル」です。このファイルは、新しい定数値を反映するように更新されています。
コミット
- コミットハッシュ:
8a70b50b1f486319a3e6c1707d49bd90192f32d8
- Author: Brad Fitzpatrick bradfitz@golang.org
- Date: Fri Sep 6 12:01:01 2013 -0700
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8a70b50b1f486319a3e6c1707d49bd90192f32d8
元コミット内容
cmd/api: include constant values
Update #5935
R=golang-dev, rsc, iant, dave
CC=golang-dev
https://golang.org/cl/13261050
変更の背景
この変更は、GoのIssue #5935 に対応するものです。Issue #5935 は、「goapi
が定数の値を出力しない」という問題提起でした。cmd/api
はGoの公開APIの変更を追跡するために設計されており、定数の値もAPIの一部と見なされるべきです。例えば、math.Pi
のような定数の値が変更された場合、それはAPIの互換性に影響を与える可能性があります。しかし、これまでの cmd/api
は定数の名前と型のみを出力し、その具体的な値は出力していませんでした。このため、定数の値の変更を自動的に検出することができませんでした。
このコミットは、cmd/api
が定数の値も出力するようにすることで、このギャップを埋め、APIの変更追跡の精度を向上させることを目的としています。
前提知識の解説
cmd/api
とは
cmd/api
は、Go言語の標準ライブラリの公開APIを抽出・比較するためのツールです。Go言語では、後方互換性を非常に重視しており、標準ライブラリのAPI変更は厳密に管理されています。cmd/api
は、Goのリリース間でAPIに意図しない変更がないかを確認するために使用されます。具体的には、Goのソースコードを解析し、エクスポートされた型、関数、変数、定数などの情報を抽出し、特定のフォーマットで出力します。この出力は「ゴールデンファイル」と比較され、差分があればAPIの変更として検出されます。
types
パッケージ
Goコンパイラは、Goのソースコードを解析する際に、コード内の要素(パッケージ、型、変数、関数など)を抽象構文木(AST)として表現し、さらに型情報として扱います。go/types
パッケージは、Goプログラムの型情報を表現するためのAPIを提供します。
types.Object
: Goプログラム内の名前付きエンティティ(変数、関数、型、定数など)を表すインターフェースです。types.Const
:types.Object
の一種で、Goの定数を表します。obj.Name()
:types.Object
のメソッドで、そのエンティティの名前(例: 定数名)を返します。obj.Type()
:types.Object
のメソッドで、そのエンティティの型(例: 定数の型)を返します。obj.Val()
:types.Const
のメソッドで、その定数の値(constant.Value
型)を返します。このコミットの核心となる部分です。
ゴールデンファイル (golden.txt
)
cmd/api
のテストでは、「ゴールデンファイル」という概念がよく使われます。これは、特定の入力(この場合はGoのソースコード)に対してツールが生成すべき期待される出力を含むファイルです。テスト実行時に、実際の出力がゴールデンファイルの内容と一致するかどうかを比較することで、ツールの挙動が正しいことを検証します。APIの変更があった場合、このゴールデンファイルも更新する必要があります。
技術的詳細
このコミットの技術的な核心は、cmd/api
が定数を処理する際に、その値も出力に含めるようにした点です。
以前の cmd/api
の実装では、emitObj
関数内で types.Const
型のオブジェクトを処理する際に、定数の名前と型のみを w.emitf("const %s %s", obj.Name(), w.typeString(obj.Type()))
の形式で出力していました。
この変更では、既存の出力に加えて、w.emitf("const %s = %s", obj.Name(), obj.Val())
という行が追加されました。これにより、定数の名前と値が =
で結合された形式で出力されるようになります。obj.Val()
メソッドは、types.Const
オブジェクトからその定数の具体的な値を取得します。この値は constant.Value
型であり、Goの定数表現を扱うためのものです。
この変更により、cmd/api
の出力は以下のようになります(例: const MyConst = 10
の場合)。
変更前:
pkg mypkg, const MyConst int
変更後:
pkg mypkg, const MyConst = 10
pkg mypkg, const MyConst int
このように、定数の値が明示的に出力されることで、cmd/api
は定数の値の変更もAPIの変更として検出できるようになります。これは、GoのAPI互換性保証において重要な改善です。
コアとなるコードの変更箇所
src/cmd/api/goapi.go
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -690,16 +690,13 @@ func (w *Walker) emitObj(obj types.Object) {
switch obj := obj.(type) {
case *types.Const:
w.emitf("const %s %s", obj.Name(), w.typeString(obj.Type()))
-
+ w.emitf("const %s = %s", obj.Name(), obj.Val())
case *types.Var:
w.emitf("var %s %s", obj.Name(), w.typeString(obj.Type()))
-
case *types.TypeName:
w.emitType(obj)
-
case *types.Func:
w.emitFunc(obj)
-
default:
panic("unknown object: " + obj.String())
}
src/cmd/api/testdata/src/pkg/p1/golden.txt
--- a/src/cmd/api/testdata/src/pkg/p1/golden.txt
+++ b/src/cmd/api/testdata/src/pkg/p1/golden.txt
@@ -1,10 +1,18 @@
+pkg p1, const A = 1
pkg p1, const A ideal-int
+pkg p1, const A64 = 1
pkg p1, const A64 int64
+pkg p1, const AIsLowerA = 11
pkg p1, const AIsLowerA ideal-int
+pkg p1, const B0 = 2
pkg p1, const B0 ideal-int
+pkg p1, const ConstChase2 = 11
pkg p1, const ConstChase2 ideal-int
+pkg p1, const ConversionConst = 5
pkg p1, const ConversionConst MyInt
+pkg p1, const FloatConst = 3/2
pkg p1, const FloatConst ideal-float
+pkg p1, const StrConst = "foo"
pkg p1, const StrConst ideal-string
pkg p1, func Bar(int8, int16, int64)
pkg p1, func Bar1(int8, int16, int64) uint64
コアとなるコードの解説
src/cmd/api/goapi.go
の変更は非常にシンプルです。emitObj
メソッド内の switch
ステートメントで *types.Const
型のオブジェクトを処理する case
ブロックに、以下の行が追加されました。
w.emitf("const %s = %s", obj.Name(), obj.Val())
w.emitf
: これはcmd/api
がAPI情報をフォーマットして出力するためのヘルパー関数です。obj.Name()
: 処理中の定数の名前(例:A
,A64
,StrConst
など)を取得します。obj.Val()
: 処理中の定数の具体的な値を取得します。この値はconstant.Value
型であり、Goの定数表現(整数、浮動小数点数、文字列など)を抽象的に扱います。emitf
はこのconstant.Value
を適切な文字列形式に変換して出力します。
この一行の追加により、cmd/api
の出力に定数の値が明示的に含まれるようになり、APIの変更追跡の粒度が向上しました。
src/cmd/api/testdata/src/pkg/p1/golden.txt
の変更は、上記のコード変更によって生成される新しい出力形式に合わせて、期待される出力(ゴールデンファイル)を更新したものです。各定数に対して、その値を含む新しい行が追加されています。例えば、pkg p1, const A = 1
のような行が追加されています。これは、コードの変更が正しく機能していることを検証するためのテストの一部です。
関連リンク
- Go Issue 5935:
cmd/api
: goapi should print constant values: https://github.com/golang/go/issues/5935 - Go CL 13261050:
cmd/api
: include constant values: https://golang.org/cl/13261050
参考にした情報源リンク
- Go言語の公式ドキュメント (GoDoc)
- Go言語のソースコード (特に
go/types
パッケージとcmd/api
ディレクトリ) - GitHubのGoリポジトリのIssueとコミット履歴