[インデックス 1038] ファイルの概要
コミット
commit c4969a3b938794817649f6609a5b2dea8b5e5fe0
Author: Russ Cox <rsc@golang.org>
Date: Mon Nov 3 15:38:27 2008 -0800
update names after 6g change
TBR=r
OCL=18381
CL=18383
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c4969a3b938794817649f6609a5b2dea8b5e5fe0
元コミット内容
このコミットは、Goのreflect
パッケージのテストファイル(src/lib/reflect/test.go
)において、型名の文字列表現を更新する変更を行いました。具体的には、期待する文字列の中で使用されていたアンダースコア(_
)をミドルドット(·
、Unicode U+00B7)に置き換えています。
変更対象となった型名表現:
*main.C_test(@)
→*main.C·test(@)
main.A_test{...}
→main.A·test{...}
main.AA_test{...}
→main.AA·test{...}
コミットメッセージの「6g change」は、当時のGoコンパイラであったアーキテクチャ固有のコンパイラ(6g、8g、5gなど)への変更を示しています。
変更の背景
2008年11月のこのコミットは、Goの初期開発段階において、コンパイラの内部的な名前マングリング(name mangling)方式が変更されたことに対応したものです。当時のGoは、以下の背景の中で開発されていました:
開発体制の変遷
- 2007年9月:Rob Pike、Robert Griesemer、Ken Thompsonが設計開始
- 2008年8月:Russ CoxがGoチームに参加(MITでPhD課程を修了中)
- 2008年当時:Goはまだプロトタイプ段階で、標準ライブラリもほとんど存在しない状態
コンパイラアーキテクチャの特徴
Goは当初からアーキテクチャ固有のコンパイラを採用していました:
- 6g: amd64アーキテクチャ用コンパイラ
- 8g: 386アーキテクチャ用コンパイラ
- 5g: ARMアーキテクチャ用コンパイラ
これらのコンパイラは、Ken ThompsonがPlan 9オペレーティングシステム向けに書いたCコンパイラをベースとしており、Plan 9の設計思想を強く反映していました。
前提知識の解説
Plan 9とGoの関係
GoのアセンブリLanguageはPlan 9アセンブラに直接基づいており、これがミドルドット文字の使用に深く関係しています。Plan 9は1980年代にBell研究所でUnixを再設計する際の設計原則の集合体であり、GoはPlan 9のC++再実装と考えることができます。
名前マングリング(Name Mangling)の必要性
コンパイラは、ソースコード中の識別子を内部的に一意な文字列に変換する必要があります。これにより:
- パッケージの名前空間を区別
- 型情報の埋め込み
- リンカでの名前衝突回避
- デバッグ情報の保持
Unicode文字の特別な扱い
ミドルドット(·、Unicode U+00B7)は、Goの内部実装において特別な意味を持ちます:
- 文字種別: Punctuation(句読点)として分類
- UTF-8エンコーディング: 0xC2 0xB7
- HTML実体参照:
·
または·
技術的詳細
ミドルドットの特殊な処理
Goのコンパイラとアセンブラにおいて、ミドルドット文字(·)は以下の特別な処理を受けます:
- オブジェクトファイルでの変換: アセンブラとCコンパイラ内で、ミドルドット(·)は通常のドット(.)に書き換えられます
- 名前空間区切り文字: 内部リンカは、ドット(.)を名前空間区切り文字として解釈します
- 可読性の向上: エンコードされたシンボル名は完全に読み取り可能で、「encoding/json.Marshal」のような形式になります
型名表現の変更理由
このコミットで変更された型名表現は、reflect.ValueToString()
メソッドの出力形式に関するものです。コンパイラの内部名前マングリング方式の変更により、リフレクションパッケージが生成する型名文字列も対応する必要がありました。
アーキテクチャ固有コンパイラの特徴
当時のGoコンパイラシステム:
- yacc/bison使用: パーサーにはyacc/bisonを使用
- C言語実装: gcコンパイラはC言語で実装
- Ken Thompson設計: Plan 9 Cコンパイラをベースとした設計
- アーキテクチャ番号: 6=amd64、8=386、5=ARM
コアとなるコードの変更箇所
変更されたファイル:src/lib/reflect/test.go
(5行の挿入、5行の削除)
変更内容の詳細
1. チャネル型の型名表現変更
// 変更前
assert(reflect.ValueToString(value), "*main.C_test(@)");
// 変更後
assert(reflect.ValueToString(value), "*main.C·test(@)");
2. 配列型の型名表現変更
// 変更前
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "main.A_test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
// 変更後
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "main.A·test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
3. スライス型の型名表現変更
// 変更前
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "main.AA_test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
// 変更後
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "main.AA·test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
コアとなるコードの解説
テストコードの構造分析
このテストファイルは、Goの初期リフレクション機能の動作を検証するものです:
1. チャネル型のリフレクション
type C chan *T; // TODO: should not be necessary
var tmp = new(C);
value := reflect.NewValue(tmp);
- ポインタ型のチャネルを定義
reflect.NewValue()
でリフレクション値を作成reflect.ValueToString()
で文字列表現を取得
2. 配列型の操作
type A [10]int;
var tmp A = A{1,2,3,4,5,6,7,8,9,10};
value := reflect.NewValue(&tmp);
- 固定長配列の定義と初期化
- ポインタを通じたリフレクション値の作成
PtrValue.Sub()
でポインタの参照先を取得ArrayValue.Elem()
で配列要素にアクセスIntValue.Put()
で値の変更
3. 初期Goの設計特徴
コメント「TODO: should not be necessary」は、当時のGo言語設計がまだ未完成で、より良い構文を模索していたことを示しています。
リフレクションAPIの初期形態
2008年当時のリフレクションAPIは現在とは大きく異なっていました:
reflect.NewValue()
: 現在のreflect.ValueOf()
に相当reflect.PtrValue
: 現在のreflect.Value
で型アサーションが必要reflect.ArrayValue
: 配列専用の型reflect.IntValue
: 整数専用の型
これらは後に統一されたreflect.Value
型に集約されました。
名前マングリングの実装詳細
アンダースコアからミドルドットへの変更は、以下の技術的理由によります:
- Unicode互換性: GoはUnicode識別子をサポートしており、ミドルドットは適切なUnicode句読点
- Plan 9継承: Plan 9アセンブラの伝統的な記法を維持
- 可読性向上: デバッグ時にシンボル名を読みやすくするため
- 名前空間明確化: パッケージ境界をより明確に示すため
関連リンク
- Go Programming Language Specification - Go言語仕様書
- The Laws of Reflection - Goのリフレクションについての公式ブログ記事
- Go at Google: Language Design in the Service of Software Engineering - Go言語設計の背景
- Plan 9 from Bell Labs - Plan 9オペレーティングシステム
- Unicode Standard Annex #31: Unicode Identifiers and Syntax - Unicode識別子の仕様
参考にした情報源リンク
- Effective Go - The Go Programming Language - Goのコーディング規約
- Go: A Documentary - Go言語の歴史的ドキュメンタリー
- Interview with Go's Russ Cox and Sameer Ajmani - The PL Enthusiast - Russ Coxのインタビュー
- Package reflect - The Go Programming Language - reflect パッケージドキュメント
- A Foray Into Go Assembly Programming - Goアセンブリプログラミング
- Unicode Character 'MIDDLE DOT' (U+00B7) - ミドルドット文字の詳細情報