[インデックス 16722] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
の変更に関するものです。具体的には、Go言語における「名前付き型 (named type)」の概念を明示的に定義し、その重要性を強調することを目的としています。この変更は、型同一性 (type identity)、代入可能性 (assignability)、およびメソッドの定義といったGo言語の根幹をなす概念をより明確にするために行われました。
コミット
commit 8268eadb9ee2a36e117c55296bbfdcf38566b641
Author: Robert Griesemer <gri@golang.org>
Date: Tue Jul 9 21:12:53 2013 -0700
spec: define notion of named type
The notion of a named type is crucial for the definition
of type identity, assignability, definitions of methods.
Explicitly introduce the notion with an extra sentence.
Fixes #5682.
R=r, rsc, iant
CC=golang-dev
https://golang.org/cl/11055043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8268eadb9ee2a36e117c55296bbfdcf38566b641
元コミット内容
このコミットの元の内容は、Go言語の仕様書に「名前付き型」の概念を導入し、それが型同一性、代入可能性、およびメソッドの定義にとって極めて重要であることを明記することです。具体的には、仕様書の「Types」セクションに名前付き型と無名型 (unnamed type) の区別を導入し、型同一性および代入可能性のルールにおいて、この新しい概念を参照するように変更しています。
変更の背景
Go言語の型システムは、その安全性と表現力の基盤をなしています。しかし、型システムの中核をなす「型同一性」や「代入可能性」といった概念を正確に理解するためには、「名前付き型」と「無名型」の区別が不可欠です。このコミット以前の仕様書では、この区別が明示的に定義されていなかったため、読者がこれらの概念を誤解する可能性がありました。
特に、以下の点が問題となっていました。
- 型同一性: Goでは、
type MyInt int
のように新しい型を定義すると、基底型が同じint
であってもMyInt
はint
とは異なる型として扱われます。これは「名前付き型」の概念に基づいています。しかし、仕様書でこの概念が明確でなかったため、なぜMyInt
とint
が異なるのか、あるいはstruct { X int }
とstruct { X int }
がなぜ同一の無名型として扱われるのかが不明瞭でした。 - 代入可能性: ある型の値を別の型の変数に代入できるかどうか(代入可能性)も、名前付き型と無名型の区別に大きく依存します。例えば、基底型が同じであれば、名前付き型と無名型の間で代入が可能な場合がありますが、そのルールは名前付き型の概念を前提としています。
- メソッドの定義: Goでは、メソッドは名前付き型に対してのみ定義できます。無名型に対して直接メソッドを定義することはできません。この重要な制約も、名前付き型の概念が明確に定義されていないと理解しにくいものでした。
これらの曖昧さを解消し、Go言語の型システムに関する理解を深めるために、Robert Griesemer氏(Go言語の共同設計者の一人)によって、名前付き型の概念を仕様書に明示的に導入するこのコミットが作成されました。これは、Go言語の設計思想における型の厳密性と明確性を追求する一環と言えます。
前提知識の解説
このコミットの変更内容を理解するためには、Go言語の以下の基本的な型システムに関する概念を理解しておく必要があります。
- 型 (Type): Goにおける型は、値が取りうる値の集合と、その値に対して実行できる操作の集合を定義します。例えば、
int
型は整数値の集合と、加算、減算などの操作を定義します。 - 型宣言 (Type Declaration): Goでは、
type NewType UnderlyingType
の形式で新しい型を宣言できます。
ここでtype MyInt int type Point struct { X, Y float64 }
MyInt
やPoint
は新しい型名です。 - 基底型 (Underlying Type): 型宣言によって新しい名前付き型が作成された場合、その新しい型は元の型(
UnderlyingType
)を基底型として持ちます。例えば、MyInt
の基底型はint
です。構造体や配列などの複合型の場合、その構造を構成する要素の型が基底型を決定します。 - 型同一性 (Type Identity): 2つの型が「同一」であるとは、それらが同じ型であるとGoコンパイラが判断することです。Goの型同一性のルールは厳密であり、特に名前付き型と無名型の間で異なります。
- 名前付き型: 型名が同じであれば同一です。
- 無名型: 構造が完全に一致していれば同一です。例えば、
struct { X int }
とstruct { X int }
は同一の無名型です。
- 代入可能性 (Assignability): ある型の値が別の型の変数に代入できるかどうかを決定するルールです。Goでは、型が厳密に一致しない場合でも、特定の条件下で代入が許可されます。例えば、基底型が同じであれば、名前付き型と無名型の間で代入が可能な場合があります。
- メソッド (Methods): Goでは、関数を特定の型に関連付けることができます。これをメソッドと呼びます。メソッドは、レシーバ引数 (receiver argument) を持つ特殊な関数です。Goのメソッドは、名前付き型に対してのみ定義できます。
これらの概念は、Go言語のプログラムがどのように動作し、型チェックがどのように行われるかを理解する上で不可欠です。
技術的詳細
このコミットの技術的詳細は、Go言語仕様書 doc/go_spec.html
の以下のセクションに対する変更に集約されます。
-
「Types」セクションへの「名前付き型」と「無名型」の導入:
- 変更前:
<p> A type determines the set of values and operations specific to values of that type. A type may be specified by a (possibly <a href="#Qualified_identifiers">qualified</a>) <a href="#Type_declarations"><i>type name</i></a> or a <i>type literal</i>, which composes a new type from previously declared types. </p>
- 変更後:
この変更により、Goの型が「名前付き型」と「無名型」に分類されることが明示されました。<p> A type determines the set of values and operations specific to values of that type. Types may be <i>named</i> or <i>unnamed</i>. Named types are specified by a (possibly <a href="#Qualified_identifiers">qualified</a>) <a href="#Type_declarations"><i>type name</i></a>; unnamed types are specified using a <i>type literal</i>, which composes a new type from existing types. </p>
- 名前付き型:
type MyInt int
のMyInt
のように、type
キーワードで宣言され、特定の名前を持つ型。組み込み型(int
,string
,bool
など)も名前付き型です。 - 無名型:
[]int
(スライス),map[string]int
(マップ),struct { X int }
(構造体),func()
(関数) のように、型リテラルによって直接構成される型で、明示的な名前を持たない型。
- 名前付き型:
- 変更前:
-
「Type identity」セクションでの「名前付き型」への参照の追加:
- 変更前:
<p> Two named types are identical if their type names originate in the same <a href="#Type_declarations">TypeSpec</a>. A named and an unnamed type are always different. Two unnamed types are identical if the corresponding type literals are identical, that is, if they have the same literal structure and corresponding components have identical types. In detail: </p>
- 変更後:
この変更は、型同一性のルールを説明する際に、新しく定義された「名前付き型」と「無名型」の概念へのリンクを追加し、読者がより正確な定義を参照できるようにしています。これにより、名前付き型と無名型の間の型同一性の厳密なルール(名前付き型と無名型は常に異なる、無名型は構造が同じであれば同一など)がより明確になります。<p> Two <a href="#Types">named types</a> are identical if their type names originate in the same <a href="#Type_declarations">TypeSpec</a>. A named and an <a href="#Types">unnamed type</a> are always different. Two unnamed types are identical if the corresponding type literals are identical, that is, if they have the same literal structure and corresponding components have identical types. In detail: </p>
- 変更前:
-
「Assignability」セクションでの「名前付き型」への参照の追加:
- 変更前:
<li> <code>x</code>'s type <code>V</code> and <code>T</code> have identical <a href="#Types">underlying types</a> and at least one of <code>V</code> or <code>T</code> is not a named type. </li>
- 変更後:
代入可能性のルールにおいても、「名前付き型」へのリンクが追加されました。これは、基底型が同じである場合に、名前付き型と無名型の間で代入が許可される条件を説明する際に、この新しい概念が重要であることを示しています。具体的には、<li> <code>x</code>'s type <code>V</code> and <code>T</code> have identical <a href="#Types">underlying types</a> and at least one of <code>V</code> or <code>T</code> is not a <a href="#Types">named type</a>. </li>
V
とT
の基底型が同一であり、かつV
またはT
の少なくとも一方が名前付き型でない場合に代入可能であるというルールが、名前付き型の概念を前提としています。
- 変更前:
これらの変更は、Go言語の型システムにおける「名前付き型」の役割を明確にし、仕様書の記述をより厳密で理解しやすいものにすることを目的としています。これにより、Goプログラマは型同一性、代入可能性、およびメソッドの定義に関するGoのルールをより正確に把握できるようになります。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、doc/go_spec.html
ファイル内の以下の3つのセクションです。
-
Types セクション:
--- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -640,10 +640,10 @@ expressions</a>. <p> A type determines the set of values and operations specific to values of that -type. A type may be specified by a -(possibly <a href="#Qualified_identifiers">qualified</a>) -<a href="#Type_declarations"><i>type name</i></a> or a <i>type literal</i>, -which composes a new type from previously declared types. +type. Types may be <i>named</i> or <i>unnamed</i>. Named types are specified +by a (possibly <a href="#Qualified_identifiers">qualified</a>) +<a href="#Type_declarations"><i>type name</i></a>; unnamed types are specified +using a <i>type literal</i>, which composes a new type from existing types. </p>
-
Type identity セクション:
--- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1358,9 +1358,9 @@ Two types are either <i>identical</i> or <i>different</i>. </p> <p> -Two named types are identical if their type names originate in the same +Two <a href="#Types">named types</a> are identical if their type names originate in the same <a href="#Type_declarations">TypeSpec</a>. -A named and an unnamed type are always different. Two unnamed types are identical +A named and an <a href="#Types">unnamed type</a> are always different. Two unnamed types are identical if the corresponding type literals are identical, that is, if they have the same literal structure and corresponding components have identical types. In detail: </p>
-
Assignability セクション:
--- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1442,7 +1442,7 @@ A value <code>x</code> is <i>assignable</i> to a variable of type <code>T</code> <li> <code>x</code>'s type <code>V</code> and <code>T</code> have identical <a href="#Types">underlying types</a> and at least one of <code>V</code> -or <code>T</code> is not a named type. +or <code>T</code> is not a <a href="#Types">named type</a>. </li>
コアとなるコードの解説
これらの変更は、Go言語の型システムにおける「名前付き型」と「無名型」の概念を仕様書に明示的に導入し、それらの概念が型同一性および代入可能性のルールにどのように影響するかを明確にすることを目的としています。
-
Types セクションの変更:
- 以前の記述では、型が「型名」または「型リテラル」によって指定されると述べていましたが、これでは「名前付き型」と「無名型」という明確な分類が欠けていました。
- 新しい記述では、「型は名前付きまたは無名である」と明確に定義しています。
- 名前付き型は「型名」によって指定されるもの。
- 無名型は「型リテラル」を使用して既存の型から新しい型を構成するもの。
- この変更は、Goの型システムを理解する上での基礎となる分類を確立し、後続のセクションでの説明の前提となります。
-
Type identity セクションの変更:
- 型同一性のルールを説明する際に、以前は単に「名前付き型」と記述していましたが、新しい記述では
<a>
タグを用いて、新しく定義された「Types」セクションの「名前付き型」へのリンクを追加しています。 - 同様に、「無名型」についても「Types」セクションへのリンクが追加されています。
- この変更は、仕様書内のクロスリファレンスを強化し、読者が「名前付き型」や「無名型」という用語の正確な定義をすぐに参照できるようにすることで、理解の正確性を高めます。これにより、Goの型同一性ルール(例:名前付き型と無名型は常に異なる)がより厳密に解釈されるようになります。
- 型同一性のルールを説明する際に、以前は単に「名前付き型」と記述していましたが、新しい記述では
-
Assignability セクションの変更:
- 代入可能性のルールの一つに、「
x
の型V
とT
が同一の基底型を持ち、かつV
またはT
の少なくとも一方が名前付き型でない場合」という条件があります。 - ここでも、「名前付き型」という記述に「Types」セクションへのリンクが追加されました。
- この変更も、型同一性セクションと同様に、仕様書内の用語の定義への参照を明確にし、代入可能性のルールが「名前付き型」の概念にどのように依存しているかを読者が正確に理解できるようにすることを目的としています。
- 代入可能性のルールの一つに、「
これらの変更は、Go言語の仕様書における用語の厳密性と一貫性を向上させ、Goの型システムに関するより正確で詳細な理解を促進します。特に、型同一性、代入可能性、そしてメソッドの定義といったGo言語の重要な側面が、名前付き型と無名型の区別によってどのように機能するかが、これらの変更によってより明確になりました。
関連リンク
- Go言語仕様書: https://go.dev/ref/spec
- Go言語仕様書(Typesセクション): https://go.dev/ref/spec#Types
- Go言語仕様書(Type identityセクション): https://go.dev/ref/spec#Type_identity
- Go言語仕様書(Assignabilityセクション): https://go.dev/ref/spec#Assignability
- Go issue #5682: spec: define notion of named type: https://github.com/golang/go/issues/5682
- Go CL 11055043: spec: define notion of named type: https://golang.org/cl/11055043
参考にした情報源リンク
- Go言語仕様書 (上記「関連リンク」に記載の公式仕様書)
- Go言語の公式Issueトラッカー (GitHub issue #5682)
- Go言語の公式コードレビューシステム (Go CL 11055043)
- Go言語に関する一般的なドキュメントやチュートリアル(Goの型システム、型同一性、代入可能性、メソッドの定義に関する解説)
- A Tour of Go: https://go.dev/tour/
- Effective Go: https://go.dev/doc/effective_go
- The Go Programming Language (Alan A. A. Donovan, Brian W. Kernighan 著) - Go言語の型システムに関する詳細な解説が含まれています。
- Go言語の型システムに関するブログ記事や解説記事(「Go named types vs. unnamed types」などで検索)
- 例: "Go: Named and Unnamed Types" by Dave Cheney (Go言語の著名な開発者による解説)
- 例: "Understanding Go's Type System" (Goの型システムに関する詳細な解説)
- Go言語のソースコード(
src/cmd/compile/internal/types/type.go
など、型システムの実装に関する部分)- Goのコンパイラがどのように型を識別し、型チェックを行うかを理解する上で参考になります。