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

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

このコミットは、Go言語の初期段階(2008年11月)におけるシンボル命名規則の大幅な変更を示しています。Russ Cox氏により実装されたこの変更では、従来のアンダースコア(_)ベースの命名規則から、Unicode文字のセンタードット(·)を使用した新しい命名規則への移行が行われました。

コミット

コミットハッシュ: c249a8de32cf5d2ceb0e896868699195b0820109
作成者: Russ Cox rsc@golang.org
日付: 2008年11月3日 15:36:08 -0800
メッセージ: "rename various magic names."

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

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

元コミット内容

このコミットでは、以下の主要な変更が行われました:

  1. sigi(シグナル・インターフェース)とsigt(シグナル・タイプ)の命名変更:

    • sys·sigi_intersigi·inter
    • sys·sigt_intsigt·int
    • Package·sigt_Typesigt·Package.Type
  2. ローカル型の命名規則変更:

    • ファイルx.go内のローカル型T: T_xT·x
    • 重複する場合の命名: T_x_1T·x·1
  3. メソッド名の命名規則変更:

    • TのメソッドM: T_MT·M
  4. 埋め込み型の適切な処理の実装

  5. init関数のみがアンダースコアを使用する規則の確立

変更の背景

このコミットは、Go言語の開発初期段階における重要な設計決定の一つです。2008年当時、Go言語はまだ公開前の状態であり、言語設計者らは最適な命名規則を模索していました。

主な背景要因:

  1. パーサーの競合回避: ピリオド(.)とスラッシュ(/)がアセンブラパーサーで句読点として扱われるため、階層的な名前の明確な表現が必要でした。

  2. Plan 9の影響: Go言語のツールチェーンはPlan 9のCコンパイラから派生しており、Plan 9では識別子でのUnicode文字の使用が積極的に採用されていました。

  3. 名前空間の明確化: パッケージパスと関数名を視覚的かつ機能的に分離する必要がありました。

前提知識の解説

センタードット(·)文字について

Unicode値: U+00B7(16進)
文字名: Middle Dot
ブロック: Latin-1 Supplement

この文字は、Go言語の内部実装において特別な意味を持ちます:

  1. アセンブリでの名前空間分離: fmt·Printfのような形式で使用
  2. オブジェクトファイルでの変換: センタードットは通常のドット(.)に変換される
  3. 内部リンカによる解釈: 名前空間分離文字として処理される

Go言語の初期開発タイムライン

  • 2007年9月21日: Robert Griesemer、Rob Pike、Ken Thompsonが設計目標を策定開始
  • 2008年1月: Ken Thompsonがコンパイラ作業を開始(C言語出力)
  • 2008年中期: 本格的なプロダクションコンパイラの開発開始
  • 2008年11月: 本コミットの実装(命名規則の大幅変更)
  • 2009年11月: Go言語の正式発表

技術的詳細

シンボル生成の変更

このコミットでは、methodsym関数の導入により、メソッドシンボルの生成方法が統一されました。

変更前の実装:

snprint(namebuf, sizeof(namebuf), "%s_%s", 
    f->sym->name, b->name);

変更後の実装:

p->to.sym = methodsym(lookup(b->name), f->type);

型情報の扱い

構造体Typeからxsymフィールドが削除され、代わりにvargenフィールドが追加されました。これにより、型の一意性の管理方法が改善されました。

埋め込み型の処理

埋め込み型の処理において、センタードットを含む名前から基本名を抽出する機能が追加されました:

enum { CenterDot = 0xB7 };
name = s->name;
if(utfrune(s->name, CenterDot)) {
    name = strdup(s->name);
    *utfrune(name, CenterDot) = 0;
}

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

1. methodsym関数の実装(src/cmd/gc/dcl.c)

Sym*
methodsym(Sym *nsym, Type *t)
{
    Sym *s;
    char buf[NSYMB];
    
    s = t->sym;
    if(s == S || isptr[t->etype] && s == t->type->sym)
        s = t->type->sym;
    if(s == S)
        goto bad;
    
    snprint(buf, sizeof(buf), "%#hT·%s", t, nsym->name);
    return pkglookup(buf, s->opackage);
    
bad:
    yyerror("illegal <this> type: %T", t);
    return S;
}

2. 型の表示形式変更(src/cmd/gc/subr.c)

if(exporting) {
    if(fp->flags & FmtShort)
        fmtprint(fp, "%hS", s);
    else
        fmtprint(fp, "%lS", s);
    if(strcmp(s->opackage, package) == 0)
    if(s->otype != t || !s->export) {
        fmtprint(fp, "·%s", filename);
        if(t->vargen)
            fmtprint(fp, "·%d", t->vargen);
    }
    return 0;
}

3. ランタイム定義の変更(src/runtime/iface.c)

// 変更前
Sigi sys·sigi_inter[2] = { (byte*)"interface {}", 0, 0, nil, 0, 0 };

// 変更後
Sigi sigi·inter[2] = { (byte*)"interface {}", 0, 0, nil, 0, 0 };

コアとなるコードの解説

methodsym関数の動作原理

methodsym関数は、メソッドのシンボル名を生成する中核的な機能です:

  1. 型情報の取得: 引数の型tからシンボルsを取得
  2. ポインタ型の処理: ポインタ型の場合、指し示される型のシンボルを使用
  3. 文字列フォーマット: %#hT·%s形式でシンボル名を構築
  4. パッケージ情報の保持: pkglookupを使用してパッケージ情報を維持

型表示の新フォーマット

新しい型表示システムでは:

  • 短縮形式: %hSフラグを使用
  • 完全形式: %lSフラグを使用
  • ローカル型の識別: ファイル名とvargenを使用した一意性の確保

エラーハンドリングの改善

従来の実装では、不正な型に対するエラーハンドリングが不十分でしたが、新しい実装ではyyerrorを使用した適切なエラー報告が実装されています。

関連リンク

参考にした情報源リンク