[インデックス 13417] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
ファイル内の「セレクタ (Selectors)」に関するセクションをクリーンアップし、明確化することを目的としています。具体的には、セレクタの動作、特に修飾識別子との違い、不正なセレクタと実行時パニックの区別、および用語の統一に焦点を当てています。
コミット
- コミットハッシュ:
71de83b73375f13db91d93a84edf555be569bea5
- 作者: Robert Griesemer gri@golang.org
- 日付: Thu Jun 28 12:22:24 2012 -0700
- コミットメッセージ:
go spec: clean up section on selectors - point out difference between selectors and qualified identifiers - differentiate between illegal selectors and run-time panics - use "indirect" as opposed to "dereference" consistently - add extra links Fixes #3779. R=r, rsc, iant, ken CC=golang-dev https://golang.org/cl/6326059
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/71de83b73375f13db91d93a84edf555be569bea5
元コミット内容
Go言語の仕様書におけるセレクタのセクションを整理し、以下の点を改善する。
- セレクタと修飾識別子の違いを明確にする。
- 不正なセレクタと実行時パニックの違いを区別する。
- 「dereference」の代わりに「indirect」を一貫して使用する。
- 追加のリンクを含める。
Issue #3779 を修正。
変更の背景
このコミットは、Go言語の仕様書におけるセレクタの記述が曖昧であったり、誤解を招く可能性があった点を修正するために行われました。特に、以下の点が課題として認識されていました。
- セレクタと修飾識別子の混同:
x.f
という構文は、x
がパッケージ名である場合は修飾識別子として機能し、x
が変数や型である場合はセレクタとして機能します。この違いが仕様書で十分に明確にされていなかったため、読者が混乱する可能性がありました。 - エラーとパニックの区別: セレクタの使用が文法的に不正である場合(コンパイル時エラー)と、実行時に
nil
ポインタやnil
インターフェースを介してアクセスしようとした結果としてパニックが発生する場合(実行時エラー)の区別が不明瞭でした。仕様書は、これらの異なる種類の「不正なアクセス」を明確に区別する必要があります。 - 用語の不統一: ポインタの逆参照に関する記述で、「dereference」と「indirect」という用語が混在しており、一貫性がありませんでした。仕様書では、用語の厳密な定義と一貫した使用が求められます。
- 情報の不足: 関連するセクションへのリンクが不足していたり、セレクタの例が適切でなかったりする点も改善の対象でした。
これらの問題は、Go言語の仕様を正確に理解し、正しくコードを記述する上で重要であり、Issue #3779 で報告された問題に対応するために、このコミットが作成されました。
前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語の概念に関する知識が必要です。
- Go言語仕様 (Go Language Specification): Go言語の構文、セマンティクス、および標準ライブラリの動作を定義する公式ドキュメントです。Go言語の「真実の源」であり、コンパイラやツールの実装、そして開発者のGoコードの理解の基盤となります。
- セレクタ (Selectors): Go言語において、
x.f
の形式で表現される式です。これは、構造体x
のフィールドf
や、型x
のメソッドf
にアクセスするために使用されます。セレクタは、埋め込みフィールド(匿名フィールド)を通じて、ネストされたフィールドやメソッドにもアクセスできます。 - 修飾識別子 (Qualified Identifiers):
package.Identifier
の形式で表現される識別子です。これは、別のパッケージで宣言された識別子(変数、関数、型など)にアクセスするために使用されます。例えば、fmt.Println
のfmt.Println
は修飾識別子です。 - 匿名フィールド (Anonymous Fields): 構造体型を定義する際に、フィールド名なしで型のみを指定して埋め込むフィールドのことです。これにより、埋め込まれた型のフィールドやメソッドが、外側の構造体のフィールドやメソッドであるかのように直接アクセスできるようになります(このメカニズムは「プロモーション」と呼ばれます)。
- ポインタの自動逆参照 (Automatic Dereferencing of Pointers): Go言語では、構造体へのポインタを通じてそのフィールドやメソッドにアクセスする際に、明示的な逆参照演算子
*
を使用する必要がありません。例えば、p
が*S
型のポインタである場合、(*p).f
と書く代わりにp.f
と書くことができます。コンパイラが自動的に逆参照を行います。 - インターフェース (Interfaces): Go言語におけるインターフェースは、メソッドのシグネチャの集合を定義する型です。特定のインターフェースのすべてのメソッドを実装する任意の型は、そのインターフェースを満たします。インターフェース型の変数には、そのインターフェースを満たす任意の型の値を代入できます。
- 実行時パニック (Run-time Panics): Goプログラムの実行中に発生する、回復不可能なエラーです。パニックが発生すると、通常のプログラムフローは停止し、スタックトレースが出力されてプログラムが終了します。一般的なパニックの原因には、
nil
ポインタの逆参照、配列の範囲外アクセス、型アサーションの失敗などがあります。 - Gerrit Change-ID (CL): Goプロジェクトでは、Gerritというコードレビューシステムが使用されています。各変更セット(コミット)は「Change List (CL)」としてGerritにアップロードされ、レビューと承認を経てマージされます。コミットメッセージに含まれる
https://golang.org/cl/XXXXXXX
の形式のリンクは、そのコミットに対応するGerrit上のCLを指します。
技術的詳細
このコミットは、doc/go_spec.html
ファイルの「Selectors」セクションに複数の重要な変更を加えています。
-
仕様書のバージョン更新:
- ファイルの冒頭にある
Subtitle
がVersion of June 26, 2012
からVersion of June 27, 2012
に更新されています。これは、仕様書の改訂日を示すものです。
- ファイルの冒頭にある
-
TODOリストの整理:
- コメントアウトされたTODOリストから
[ ] review language on implicit dereferencing
の項目が削除されています。これは、このコミットでポインタの自動逆参照に関する記述が改善されたため、このTODOが完了したことを示唆しています。
- コメントアウトされたTODOリストから
-
セレクタの例の修正:
- セレクタの例として不適切だった
math.Sin
が削除されています。math.Sin
はパッケージmath
の関数Sin
を参照する「修飾識別子」の例であり、セレクタの例としては適切ではありませんでした。セレクタは、obj.color
のように、構造体のフィールドやメソッドにアクセスする際に使用されます。
- セレクタの例として不適切だった
-
セレクタの定義の明確化:
- セレクタの導入部分の記述が大幅に修正されています。
- 変更前:
A primary expression of the form x.f
- 変更後:
For a <a href="#Primary_expressions">primary expression</a> <code>x</code> that is not a <a href="#Package_clause">package name</a>, the <i>selector expression</i>
- 変更前:
- この変更により、
x
が「パッケージ名ではない」場合にx.f
がセレクタ式であることを明確にしています。これにより、x
がパッケージ名である場合の「修飾識別子」との混同を防ぎ、読者を適切なセクション(Qualified_identifiers
)に誘導しています。
- セレクタの導入部分の記述が大幅に修正されています。
-
修飾識別子への誘導:
- セレクタの定義の段落に、
If <code>x</code> is a package name, see the section on <a href="#Qualified_identifiers">qualified identifiers</a>.
という文が追加されました。これにより、x.f
構文がパッケージ名に適用される場合の動作について、読者が正しい情報源を参照できるようになります。
- セレクタの定義の段落に、
-
匿名フィールドの記述の修正:
- 匿名フィールドに関する記述で、
nested anonymous field of T
がnested <a href="#Struct_types">anonymous field</a> of <code>T</code>
に変更され、Struct_types
セクションへのリンクが追加されました。これにより、匿名フィールドの概念がより正確に、かつ関連情報へのアクセスが容易になっています。
- 匿名フィールドに関する記述で、
-
セレクタのルールに関する追加と明確化:
- セレクタの適用ルールを列挙したリストに、新しい項目が追加されました。
If <code>x</code> is of pointer or interface type and has the value <code>nil</code>, assigning to, evaluating, or calling <code>x.f</code> causes a <a href="#Run_time_panics">run-time panic</a>.
- この新しいルールは、
nil
ポインタやnil
インターフェースを介してセレクタアクセスを行った場合に、実行時パニックが発生することを明確に規定しています。これにより、コンパイル時エラーとなる「不正なセレクタ」と、実行時エラーとなる「パニック」の区別が明確になります。 - 既存のルールも、インターフェース型
I
の変数x
に対するx.f
の動作について、より厳密な表現に修正されています。特に、I
のメソッドセットにf
が存在しない場合にセレクタ式が「illegal(不正)」であるという点が強調されています。
- セレクタの適用ルールを列挙したリストに、新しい項目が追加されました。
-
用語の統一とリンクの追加:
- 「Selectors automatically dereference pointers to structs.」という文が「Selectors automatically dereference pointers to structs.」に変更され、
Address_operators
セクションへのリンクが追加されました。 - さらに、コミットメッセージにある「use "indirect" as opposed to "dereference" consistently」という指示にもかかわらず、この特定の変更では「dereference」という単語が残っています。しかし、全体的な文脈として、ポインタの自動逆参照の概念をより正確に説明するために、関連するセクションへのリンクが追加されたと解釈できます。Go言語の仕様では、「dereference」という言葉自体はポインタ演算子
*
の文脈で使われることが多く、セレクタの文脈では「indirect」という言葉がより適切であるという議論があった可能性があります。このコミットでは、その一貫性を図るための第一歩として、関連する概念へのリンクを追加したと考えられます。
- 「Selectors automatically dereference pointers to structs.」という文が「Selectors automatically dereference pointers to structs.」に変更され、
これらの変更は、Go言語の仕様書がより正確で、曖昧さがなく、読者にとって理解しやすいものとなるように貢献しています。
コアとなるコードの変更箇所
変更はすべて doc/go_spec.html
ファイルに対して行われています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of June 26, 2012",
+ "Subtitle": "Version of June 27, 2012",
"Path": "/ref/spec"
}-->
@@ -15,7 +15,6 @@ TODO
[ ] need explicit language about the result type of operations
[ ] should probably write something about evaluation order of statements even
though obvious
-[ ] review language on implicit dereferencing
-->
@@ -2324,7 +2323,6 @@ Point{1, 2}
m["foo"]
s[i : j + 1]
obj.color
-math.Sin
f.p[i].x()
</pre>
@@ -2332,7 +2330,9 @@ f.p[i].x()
<h3 id="Selectors">Selectors</h3>
<p>
-A primary expression of the form
+For a <a href="#Primary_expressions">primary expression</a> <code>x</code>
+that is not a <a href="#Package_clause">package name</a>, the
+<i>selector expression</i>
</p>
<pre>
@@ -2340,17 +2340,20 @@ x.f
</pre>
<p>
-denotes the field or method <code>f</code> of the value denoted by <code>x</code>
-(or sometimes <code>*x</code>; see below). The identifier <code>f</code>
-is called the (field or method)\n-<i>selector</i>; it must not be the <a href="#Blank_identifier">blank identifier</a>.\n-The type of the expression is the type of <code>f</code>.\n+denotes the field or method <code>f</code> of the value <code>x</code>
+(or sometimes <code>*x</code>; see below).\n+The identifier <code>f</code> is called the (field or method) <i>selector</i>;\n+it must not be the <a href="#Blank_identifier">blank identifier</a>.\n+The type of the selector expression is the type of <code>f</code>.\n+If <code>x</code> is a package name, see the section on\n+<a href="#Qualified_identifiers">qualified identifiers</a>.\n </p>\n+\n <p>\n A selector <code>f</code> may denote a field or method <code>f</code> of\n a type <code>T</code>, or it may refer\n-to a field or method <code>f</code> of a nested anonymous field of\n-<code>T</code>.\n+to a field or method <code>f</code> of a nested\n+<a href="#Struct_types">anonymous field</a> of <code>T</code>.\n The number of anonymous fields traversed\n to reach <code>f</code> is called its <i>depth</i> in <code>T</code>.\n The depth of a field or method <code>f</code>\n@@ -2359,9 +2362,11 @@ The depth of a field or method <code>f</code> declared in\n an anonymous field <code>A</code> in <code>T</code> is the\n depth of <code>f</code> in <code>A</code> plus one.\n </p>\n+\n <p>\n The following rules apply to selectors:\n </p>\n+\n <ol>\n <li>\n For a value <code>x</code> of type <code>T</code> or <code>*T</code>\n@@ -2373,18 +2378,26 @@ If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code><\n with shallowest depth, the selector expression is illegal.\n </li>\n <li>\n-For a variable <code>x</code> of type <code>I</code>\n-where <code>I</code> is an interface type,\n-<code>x.f</code> denotes the actual method with name <code>f</code> of the value assigned\n-to <code>x</code> if there is such a method.\n-If no value or <code>nil</code> was assigned to <code>x</code>, <code>x.f</code> is illegal.\n+For a variable <code>x</code> of type <code>I</code> where <code>I</code>\n+is an interface type, <code>x.f</code> denotes the actual method with name\n+<code>f</code> of the value assigned to <code>x</code>.\n+If there is no method with name <code>f</code> in the\n+<a href="#Method_sets">method set</a> of <code>I</code>, the selector\n+expression is illegal.\n </li>\n <li>\n In all other cases, <code>x.f</code> is illegal.\n </li>\n+<li>\n+If <code>x</code> is of pointer or interface type and has the value\n+<code>nil</code>, assigning to, evaluating, or calling <code>x.f</code>\n+causes a <a href="#Run_time_panics">run-time panic</a>.\n+</i>\n </ol>\n+\n <p>\n-Selectors automatically dereference pointers to structs.\n+Selectors automatically <a href="#Address_operators">dereference</a>\n+pointers to structs.\n If <code>x</code> is a pointer to a struct, <code>x.y</code>\n is shorthand for <code>(*x).y</code>; if the field <code>y</code>\n is also a pointer to a struct, <code>x.y.z</code> is shorthand\n@@ -2393,6 +2406,7 @@ If <code>x</code> contains an anonymous field of type <code>*A</code>,\n where <code>A</code> is also a struct type,\n <code>x.f</code> is a shortcut for <code>(*x.A).f</code>.\n </p>\n+\n <p>\n For example, given the declarations:\n </p>
コアとなるコードの解説
このコミットの核となる変更は、Go言語仕様の「セレクタ」セクションの記述をより正確で、誤解の少ないものにすることです。
-
セレクタの定義の厳密化:
- 以前の記述では、
x.f
という形式の式がすべてセレクタであるかのように読める可能性がありました。しかし、x
がパッケージ名である場合(例:fmt.Println
)、これはセレクタではなく「修飾識別子」です。 - 新しい記述
For a primary expression x that is not a package name, the selector expression
は、x
がパッケージ名ではない場合にのみx.f
がセレクタであることを明確にしています。これにより、セレクタと修飾識別子の概念的な区別が仕様レベルで明確になりました。 - さらに、
If x is a package name, see the section on qualified identifiers.
という文を追加することで、読者が修飾識別子に関する正しい情報源に容易にアクセスできるように配慮されています。
- 以前の記述では、
-
不正なセレクタと実行時パニックの区別:
- Go言語では、コンパイル時に検出される文法的なエラー(「illegal」と表現される)と、実行時に発生するエラー(「run-time panic」と表現される)は明確に区別されます。
- このコミットでは、セレクタのルールに新しい項目
If x is of pointer or interface type and has the value nil, assigning to, evaluating, or calling x.f causes a run-time panic.
を追加しました。これは、nil
ポインタやnil
インターフェースを介してフィールドやメソッドにアクセスしようとすると、コンパイルエラーではなく実行時パニックが発生するという重要な動作を明記したものです。 - これにより、仕様書は、プログラマがコードの健全性を判断する上で不可欠な、コンパイル時と実行時のエラー挙動の違いを明確に示しています。
-
用語の一貫性:
- コミットメッセージには「use "indirect" as opposed to "dereference" consistently」とありますが、提供された差分では「dereference」という単語が残っています。しかし、
Selectors automatically <a href="#Address_operators">dereference</a> pointers to structs.
のように、関連する概念(アドレス演算子)へのリンクが追加されています。これは、用語の厳密な定義と、関連する仕様セクションへの誘導を通じて、読者の理解を深めることを意図しています。Go言語の文脈では、「dereference」は*
演算子による明示的な逆参照を指すことが多く、セレクタによる暗黙的なアクセスは「indirect」と表現されることがより適切であるというニュアンスがあります。この変更は、その一貫性への第一歩と見なせます。
- コミットメッセージには「use "indirect" as opposed to "dereference" consistently」とありますが、提供された差分では「dereference」という単語が残っています。しかし、
-
仕様書の品質向上:
math.Sin
のような不適切な例の削除や、匿名フィールドに関する記述の修正、TODOリストの整理などは、仕様書全体の品質と正確性を向上させるための細かな改善です。これにより、Go言語の仕様がより堅牢で、学習者や実装者にとって信頼できる情報源となります。
これらの変更は、Go言語のセマンティクスをより正確に定義し、開発者が言語の挙動をより深く理解するのに役立ちます。
関連リンク
- Go Issue #3779: このコミットが修正したとされるGoのIssue。Goプロジェクトの公式Issueトラッカーで詳細を確認できます。
- https://github.com/golang/go/issues/3779 (一般的なGoのIssueトラッカーのURL形式。正確なIssueはGoの公式リポジトリで確認が必要)
- Gerrit Change-ID 6326059: このコミットに対応するGerrit上の変更リスト。
参考にした情報源リンク
- The Go Programming Language Specification: Go言語の公式仕様書。
- Go Project on GitHub: Go言語のソースコードリポジトリ。
- Gerrit Code Review: Goプロジェクトが使用するコードレビューシステム。