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

[インデックス 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言語の公式ドキュメント (GoDoc)
  • Go言語のソースコード (特に go/types パッケージと cmd/api ディレクトリ)
  • GitHubのGoリポジトリのIssueとコミット履歴