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

[インデックス 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実体参照: &middot; または &#183;

技術的詳細

ミドルドットの特殊な処理

Goのコンパイラとアセンブラにおいて、ミドルドット文字(·)は以下の特別な処理を受けます:

  1. オブジェクトファイルでの変換: アセンブラとCコンパイラ内で、ミドルドット(·)は通常のドット(.)に書き換えられます
  2. 名前空間区切り文字: 内部リンカは、ドット(.)を名前空間区切り文字として解釈します
  3. 可読性の向上: エンコードされたシンボル名は完全に読み取り可能で、「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型に集約されました。

名前マングリングの実装詳細

アンダースコアからミドルドットへの変更は、以下の技術的理由によります:

  1. Unicode互換性: GoはUnicode識別子をサポートしており、ミドルドットは適切なUnicode句読点
  2. Plan 9継承: Plan 9アセンブラの伝統的な記法を維持
  3. 可読性向上: デバッグ時にシンボル名を読みやすくするため
  4. 名前空間明確化: パッケージ境界をより明確に示すため

関連リンク

参考にした情報源リンク