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

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

このコミットは、Go言語の初期開発段階におけるコードベースの一部変更を記録しています。具体的には、usr/gri/pretty ディレクトリ内の複数のGoソースファイルにおいて、構造体(struct)のフィールド名の命名規則を修正しています。これは、Go言語におけるエクスポートされた(公開された)フィールドの命名規則に準拠させるための変更であり、フィールド名の先頭文字を小文字から大文字に「casify(ケースを変更する)」しています。

コミット

commit 626d25065dd5c0e99ddd7504567dab7fa5fa087c
Author: Robert Griesemer <gri@golang.org>
Date:   Fri Jan 16 15:31:34 2009 -0800

    casify struct fields
    
    R=r
    OCL=22998
    CL=22998
--
 usr/gri/pretty/ast.go         |  6 +++---
 usr/gri/pretty/compilation.go | 22 +++++++++++-----------
 usr/gri/pretty/parser.go      |  2 +--
 usr/gri/pretty/pretty.go      | 16 ++++++++--------
 4 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go
index 29d183391e..84c404eb78 100644
--- a/usr/gri/pretty/ast.go
+++ b/usr/gri/pretty/ast.go
@@ -99,14 +99,14 @@ export func NewObject(pos, kind int, ident string) *Object {
 // Scopes
 
 export type Scope struct {
-	parent *Scope;
+	Parent *Scope;
  entries map[string] *Object;
 }
 
 
 export func NewScope(parent *Scope) *Scope {
  scope := new(Scope);
-	scope.parent = parent;
+	scope.Parent = parent;
  scope.entries = make(map[string]*Object, 8);
  return scope;
 }
@@ -127,7 +127,7 @@ func (scope *Scope) Lookup(ident string) *Object {
  if obj != nil {
  return obj;
  }
-		scope = scope.parent;
+		scope = scope.Parent;
  }
  return nil;
 }
diff --git a/usr/gri/pretty/compilation.go b/usr/gri/pretty/compilation.go
index ad802566f9..1d8f3cf1dd 100644
--- a/usr/gri/pretty/compilation.go
+++ b/usr/gri/pretty/compilation.go
@@ -24,13 +24,13 @@ func assert(b bool) {
 
 
 export type Flags struct {
-	verbose bool;
-	sixg bool;
-	deps bool;
-	columns bool;
-	testmode bool;
-	tokenchan bool;
-	naming bool;
+	Verbose bool;
+	Sixg bool;
+	Deps bool;
+	Columns bool;
+	Testmode bool;
+	Tokenchan bool;
+	Naming bool;
 }
 
 
@@ -125,18 +125,18 @@ export func Compile(src_file string, flags *Flags) (*AST.Program, int) {
  }
 
  var err errorHandler;
-	err.Init(src_file, src, flags.columns);
+	err.Init(src_file, src, flags.Columns);
 
  var scanner Scanner.Scanner;
-	scanner.Init(&err, src, true, flags.testmode);
+	scanner.Init(&err, src, true, flags.Testmode);
 
  var tstream <-chan *Scanner.Token;
-	if flags.tokenchan {
+	if flags.Tokenchan {
  tstream = scanner.TokenStream();
  }
 
  var parser Parser.Parser;
-	parser.Open(flags.verbose, flags.sixg, flags.deps, flags.naming, &scanner, tstream);
+	parser.Open(flags.Verbose, flags.Sixg, flags.Deps, flags.Naming, &scanner, tstream);
 
  prog := parser.ParseProgram();
 
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index 1f975682e0..d72eeccd89 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -160,7 +160,7 @@ func (P *Parser) OpenScope() {
 
 
 func (P *Parser) CloseScope() {
-	P.top_scope = P.top_scope.parent;
+	P.top_scope = P.top_scope.Parent;
 }
 
 
diff --git a/usr/gri/pretty/pretty.go b/usr/gri/pretty/pretty.go
index 1d6ad575f0..94233ee44d 100644
--- a/usr/gri/pretty/pretty.go
+++ b/usr/gri/pretty/pretty.go
@@ -18,14 +18,14 @@ var (\n )\n \n func init() {\n-	Flag.BoolVar(&flags.verbose, \"v\", false, \"verbose mode: trace parsing\");\n-	Flag.BoolVar(&flags.sixg, \"6g\", true, \"6g compatibility mode\");\n+	Flag.BoolVar(&flags.Verbose, \"v\", false, \"verbose mode: trace parsing\");\n+	Flag.BoolVar(&flags.Sixg, \"6g\", true, \"6g compatibility mode\");\n  //TODO fix this code again\n-	//Flag.BoolVar(&flags.deps, \"d\", false, \"print dependency information only\");\n-	Flag.BoolVar(&flags.columns, \"columns\", Platform.USER == \"gri\", \"print column info in error messages\");\n-	Flag.BoolVar(&flags.testmode, \"t\", false, \"test mode: interprets /* ERROR */ and /* SYNC */ comments\");\n-	Flag.BoolVar(&flags.tokenchan, \"token_chan\", false, \"use token channel for scanner-parser connection\");\n-	Flag.BoolVar(&flags.naming, \"naming\", false, \"verify export naming scheme\");\n+	//Flag.BoolVar(&flags.Deps, \"d\", false, \"print dependency information only\");\n+	Flag.BoolVar(&flags.Columns, \"columns\", Platform.USER == \"gri\", \"print column info in error messages\");\n+	Flag.BoolVar(&flags.Testmode, \"t\", false, \"test mode: interprets /* ERROR */ and /* SYNC */ comments\");\n+	Flag.BoolVar(&flags.Tokenchan, \"token_chan\", false, \"use token channel for scanner-parser connection\");\n+	Flag.BoolVar(&flags.Naming, \"naming\", false, \"verify export naming scheme\");\n }\n \n \n@@ -55,7 +55,7 @@ func main() {\n  if nerrors > 0 {\n  return;\n  }\n-			if !flags.naming && !*silent && !flags.testmode {\n+			if !flags.Naming && !*silent && !flags.Testmode {\n  Printer.Print(prog);\n  }\n  }\n```

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

[https://github.com/golang/go/commit/626d25065dd5c0e99ddd7504567dab7fa5fa087c](https://github.com/golang/go/commit/626d25065dd5c0e99ddd7504567dab7fa5fa087c)

## 元コミット内容

このコミットの元々のメッセージは「casify struct fields」です。これは、構造体のフィールド名をGo言語の命名規則に合わせて「ケースを変更する」、つまり小文字から大文字に変換することを意味しています。

## 変更の背景

Go言語は、その設計思想の一つとして「シンプルさ」と「明瞭さ」を重視しています。その一環として、識別子(変数名、関数名、型名、構造体フィールド名など)の可視性(エクスポートされるか否か)を、その識別子の先頭文字のケース(大文字か小文字か)によって決定するというユニークなルールを採用しています。

-   **大文字で始まる識別子**: パッケージ外からアクセス可能(エクスポートされる)
-   **小文字で始まる識別子**: パッケージ内でのみアクセス可能(エクスポートされない)

このコミットが行われた2009年1月は、Go言語がまだ一般に公開される前の初期開発段階でした。この時期は、言語仕様や標準ライブラリの設計が固まりつつある過渡期であり、このような基本的な命名規則の適用も進められていました。

`usr/gri/pretty` ディレクトリは、Go言語の初期のパーサーやコンパイラ、AST(抽象構文木)関連のコードが含まれていたと推測されます。このような基盤となるコードにおいて、Go言語の設計原則に沿った命名規則を早期に適用することは、コードベースの一貫性を保ち、将来的な開発の効率性を高める上で非常に重要でした。

したがって、この変更の背景には、Go言語のコアな命名規則をコードベース全体に徹底し、言語の設計思想を反映させるという意図があります。

## 前提知識の解説

### Go言語の命名規則と可視性

Go言語における識別子の可視性(エクスポートされるか否か)は、その識別子の最初の文字のケースによって決まります。

-   **エクスポートされた識別子 (Exported Identifiers)**:
    -   名前が**大文字**で始まる識別子(例: `Name`, `Age`, `NewObject`, `Compile`)。
    -   これらは、その識別子が定義されているパッケージの外部からアクセス可能です。他のプログラミング言語における `public` メンバーに相当します。
    -   構造体のフィールドがエクスポートされている場合、そのフィールドは他のパッケージから読み書きできます。
    -   関数がエクスポートされている場合、その関数は他のパッケージから呼び出すことができます。

-   **エクスポートされない識別子 (Unexported Identifiers)**:
    -   名前が**小文字**で始まる識別子(例: `name`, `age`, `newObject`, `compile`)。
    -   これらは、その識別子が定義されているパッケージの内部からのみアクセス可能です。他のプログラミング言語における `private` または `internal` メンバーに相当します。
    -   構造体のフィールドがエクスポートされない場合、そのフィールドは同じパッケージ内からのみアクセスでき、外部からは直接アクセスできません。

このシンプルながら強力なメカニズムは、Go言語のAPI設計において重要な役割を果たします。開発者は、識別子の命名だけでその可視性を明確に判断でき、不必要な内部実装の詳細を外部に公開することを防ぐことができます。

### 構造体 (Struct)

Go言語における構造体は、異なる型のフィールド(データ)をまとめるためのユーザー定義型です。C言語の `struct` やJava/C++のクラスのデータ部分に似ています。

```go
type Person struct {
    Name string // エクスポートされたフィールド
    age  int    // エクスポートされないフィールド
}

上記の例では、Name フィールドは大文字で始まるためエクスポートされ、age フィールドは小文字で始まるためエクスポートされません。

AST (Abstract Syntax Tree)

AST(抽象構文木)は、ソースコードの抽象的な構文構造を木構造で表現したものです。コンパイラやインタプリタがソースコードを解析する際に中間表現として生成されます。このコミットで変更されている ast.go ファイルは、Go言語のパーサーが生成するASTのノード定義を含んでいたと考えられます。

Go言語の初期開発

Go言語は、GoogleのRobert Griesemer、Rob Pike、Ken Thompsonによって2007年に設計が開始され、2009年11月に一般公開されました。このコミットは2009年1月のものであり、まさに一般公開に向けて言語仕様や標準ライブラリが整備されている最中の変更です。Robert GriesemerはGo言語の主要な設計者の一人であり、彼のコミットは言語の根幹に関わる変更が多いことを示唆しています。

技術的詳細

このコミットは、Go言語の命名規則、特に構造体フィールドの可視性に関する規則をコードベースに適用するものです。変更内容は非常にシンプルで、特定の構造体フィールドの先頭文字を小文字から大文字に変更し、それに伴いそのフィールドを参照している箇所も同様に大文字に変更しています。

具体的には、以下の構造体フィールドが変更されています。

  1. Scope 構造体の parent フィールド:

    • parent *Scope; から Parent *Scope; へ変更。
    • Scope はスコープ(変数の有効範囲)を管理するための構造体であり、parent は親スコープへのポインタを保持していました。このフィールドがエクスポートされることで、パッケージ外からスコープの階層構造にアクセスできるようになります。これは、デバッグツールやリフレクションなど、言語の内部構造を検査するようなツールを開発する際に有用です。
  2. Flags 構造体の複数のフィールド:

    • verbose bool; から Verbose bool;
    • sixg bool; から Sixg bool;
    • deps bool; から Deps bool;
    • columns bool; から Columns bool;
    • testmode bool; から Testmode bool;
    • tokenchan bool; から Tokenchan bool;
    • naming bool; から Naming bool;
    • Flags 構造体は、コンパイラやパーサーの動作を制御するための各種フラグ(オプション)を保持していました。これらのフラグがエクスポートされることで、外部からこれらの設定にアクセスしたり、設定を変更したりすることが可能になります。これは、コマンドラインツールやIDE(統合開発環境)がコンパイラの挙動を制御する際に必要となる機能です。例えば、go build コマンドのオプションが内部的にこれらのフラグに対応している可能性があります。

これらの変更は、単なる命名規則の統一だけでなく、Go言語のAPI設計における「何を公開し、何を隠蔽するか」という設計思想を反映しています。これらのフィールドをエクスポートすることで、Go言語のコンパイラやツールチェインの内部構造の一部が、よりプログラム的にアクセス可能になり、拡張性や統合性が向上します。

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

このコミットでは、以下の4つのファイルが変更されています。

  1. usr/gri/pretty/ast.go:

    • Scope 構造体の parent フィールドが Parent に変更され、それに伴い参照箇所も修正。
    • scope.parent = parent; -> scope.Parent = parent;
    • scope = scope.parent; -> scope = scope.Parent;
  2. usr/gri/pretty/compilation.go:

    • Flags 構造体の全てのブール型フィールド(verbose, sixg, deps, columns, testmode, tokenchan, naming)が、それぞれ先頭大文字の Verbose, Sixg, Deps, Columns, Testmode, Tokenchan, Naming に変更。
    • これらのフィールドを参照している箇所も全て修正。
      • flags.columns -> flags.Columns
      • flags.testmode -> flags.Testmode
      • flags.tokenchan -> flags.Tokenchan
      • flags.verbose -> flags.Verbose
      • flags.sixg -> flags.Sixg
      • flags.deps -> flags.Deps
      • flags.naming -> flags.Naming
  3. usr/gri/pretty/parser.go:

    • P.top_scope.parent の参照が P.top_scope.Parent に変更。
  4. usr/gri/pretty/pretty.go:

    • Flag.BoolVar の呼び出しにおいて、flags 構造体のフィールド名が小文字から大文字に変更。
    • flags.namingflags.testmode の参照が flags.Namingflags.Testmode に変更。

コアとなるコードの解説

変更されたコードは、Go言語の初期のコンパイラ/ツールチェインの一部である pretty パッケージ内の構造体定義とその使用箇所です。

usr/gri/pretty/ast.go の変更

Scope 構造体は、Goプログラムのシンボル解決(変数や関数の名前がどの定義に対応するかを決定するプロセス)において重要な役割を果たすスコープの概念を表現しています。 parent *Scope フィールドは、現在のスコープがネストされている場合に、その親スコープへの参照を保持していました。このフィールドが Parent *Scope と大文字で始まるように変更されたことで、Scope 構造体のインスタンスが他のパッケージからアクセスされた際に、その親スコープの情報も参照できるようになりました。これは、デバッガやコード分析ツールがプログラムの実行コンテキストやシンボルテーブルを検査する際に役立ちます。

usr/gri/pretty/compilation.go および usr/gri/pretty/pretty.go の変更

Flags 構造体は、コンパイルや解析のプロセスにおける様々なオプションや設定をカプセル化しています。例えば、verbose は詳細なログ出力を有効にするか、testmode はテストモードを有効にするか、といったブール値のフラグです。 これらのフィールドが全て大文字で始まるように変更されたことで、Flags 構造体のインスタンスが他のパッケージに渡された際に、これらの設定値を外部から読み書きできるようになりました。これは、Go言語のコンパイラやツールチェインが、コマンドライン引数や設定ファイルを通じて外部から設定を注入されることを可能にするための変更です。例えば、go build -v のようなコマンドは、内部的に Flags.Verbosetrue に設定している可能性があります。

usr/gri/pretty/parser.go の変更

Parser 構造体は、Goソースコードを解析してASTを構築する役割を担っています。P.top_scope は現在のトップレベルスコープを指し、その parent フィールドを通じてスコープの階層を辿っていました。この参照が P.top_scope.Parent に変更されたのは、Scope 構造体内のフィールド名変更に合わせたものです。これにより、パーサーがスコープの出入りを管理するロジックが、Go言語の命名規則に準拠する形になりました。

全体として、これらの変更はGo言語の初期段階におけるコードベースの「クリーンアップ」と「標準化」の一環であり、言語の設計原則である「可視性は命名規則によって決定される」というルールを徹底するためのものです。これにより、Go言語のコードベースはより一貫性があり、将来的な拡張やメンテナンスが容易になる基盤が築かれました。

関連リンク

参考にした情報源リンク