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

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

このコミットは、Go言語の仕様書(doc/go_spec.html)における「基底型(underlying type)」の定義をより正確にするための変更です。特に、errorのような事前宣言された型(predeclared types)の基底型に関する記述が修正されています。

コミット

commit 8d77d2c8f0f31159025cd0ddfb4d92147d659ca4
Author: Robert Griesemer <gri@golang.org>
Date:   Wed Mar 5 19:37:44 2014 -0800

    spec: be more precise about underlying types of predeclared types
    
    The underlying type of the predeclared type error is not itself,
    but the interface it is defined as.
    
    Fixes #7444.
    
    LGTM=r, rsc
    R=r, rsc, iant, ken
    CC=golang-codereviews
    https://golang.org/cl/71790044

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

https://github.com/golang/go/commit/8d77d2c8f0f31159025cd0ddfb4d92147d659ca4

元コミット内容

このコミットの目的は、Go言語の仕様書において、事前宣言された型(predeclared types)の基底型に関する記述をより正確にすることです。具体的には、errorのような事前宣言された型は、それ自体が基底型なのではなく、それが定義されているインターフェースが基底型であるという点を明確にしています。

変更の背景

Go言語の型システムにおいて、「基底型(underlying type)」は非常に重要な概念です。これは、型の同一性(type identity)や代入可能性(assignability)のルールを決定する上で中心的な役割を果たします。

以前の仕様では、すべての事前宣言された型(bool, int, string, errorなど)は、それ自体が自身の基底型であると記述されていました。しかし、これはerror型のようなインターフェース型にとっては誤解を招く可能性がありました。errorは、実際にはinterface{ Error() string }として定義されており、その基底型はこのインターフェース型であるべきです。

この不正確さが、Go言語の型システムを深く理解しようとする開発者にとって混乱の原因となる可能性がありました。特に、型アサーションや型変換、インターフェースの振る舞いを正確に把握するためには、基底型の定義が厳密である必要があります。このコミットは、この仕様の曖昧さを解消し、より正確な型システムの説明を提供することを目的としています。

コミットメッセージに記載されているFixes #7444は、この変更が特定の課題(issue)を解決したことを示唆していますが、現在の公開されているGoリポジトリのissueトラッカーには該当する番号のissueが見つかりませんでした。これは、内部的なトラッキング番号であるか、あるいは非常に古いissueであるため、現在の公開データベースには存在しない可能性があります。しかし、変更内容から、error型の基底型に関する仕様の明確化が目的であったことは明らかです。

前提知識の解説

このコミットの変更を理解するためには、以下のGo言語の概念を理解しておく必要があります。

  1. 型(Type): Go言語におけるデータがどのような種類であるかを示す分類です。例えば、intは整数型、stringは文字列型です。
  2. 事前宣言された型(Predeclared Types): Go言語の仕様によってあらかじめ定義されている組み込みの型です。例として、bool, int, float64, string, errorなどがあります。
  3. 基底型(Underlying Type): Go言語の型システムにおける重要な概念です。各型Tには基底型が存在します。
    • 型宣言(type MyInt int)によって新しい型が定義された場合、その新しい型の基底型は、元の型の基底型と同じになります。例えば、type MyInt intの場合、MyIntの基底型はintの基底型(つまりint自身)です。
    • 基底型は、型の同一性や代入可能性のルールに影響を与えます。異なる名前の型であっても、基底型が同じであれば、特定の条件下で互換性を持つことがあります。
  4. インターフェース型(Interface Type): メソッドのシグネチャの集合を定義する型です。インターフェース型は、そのインターフェースが定義するすべてのメソッドを実装する任意の具象型の値を保持できます。Go言語の多態性(polymorphism)を実現する主要なメカニズムです。
    • error型は、Go言語でエラーを表現するために使用される事前宣言されたインターフェース型です。その定義はtype error interface { Error() string }です。

技術的詳細

このコミットは、Go言語の仕様書(doc/go_spec.html)の「Types」セクションにある「Underlying types」の定義を修正しています。

変更前の記述は以下の通りでした。

Each type T has an underlying type: If T is a predeclared type or a type literal, the corresponding underlying type is T itself.

これは、「各型Tには基底型がある。もしTが事前宣言された型、または型リテラルであれば、対応する基底型はT自身である」という意味です。この記述では、errorのようなインターフェース型を含むすべての事前宣言された型が、それ自体を基底型として持つことになります。

変更後の記述は以下の通りです。

Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself. Otherwise, T's underlying type is the underlying type of the type to which T refers in its type declaration.

この変更により、事前宣言された型の中でも、bool, numeric(整数型、浮動小数点型、複素数型など)、string型のみが、それ自体を基底型として持つことが明確にされました。

その他の事前宣言された型(例えばerror)については、「そうでなければ、Tの基底型は、Tが型宣言で参照する型の基底型である」というルールが適用されます。

具体的にerror型にこのルールを適用すると、errorinterface{ Error() string }として定義されているため、その基底型はinterface{ Error() string }の基底型、つまりinterface{ Error() string }自身となります。これにより、error型の基底型がerror自身ではなく、それが定義されているインターフェース型であることが明確になります。

この修正は、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 March 5, 2014",
+ 	"Subtitle": "Version of March 6, 2014",
  	"Path": "/ref/spec"
 }-->
 
@@ -674,7 +674,8 @@ types, the dynamic type is always the static type.
 
 <p>
 Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
-is a predeclared type or a type literal, the corresponding underlying
+is one of the predeclared boolean, numeric, or string types, or a type literal,
+the corresponding underlying
 type is <code>T</code> itself. Otherwise, <code>T</code>\'s underlying type
 is the underlying type of the type to which <code>T</code> refers in its
 <a href="#Type_declarations">type declaration</a>.

コアとなるコードの解説

変更は主に以下の2点です。

  1. 仕様書のバージョン日付の更新:

    - 	"Subtitle": "Version of March 5, 2014",
    + 	"Subtitle": "Version of March 6, 2014",
    

    これは、仕様書が更新された日付を反映する単純な変更です。

  2. 基底型の定義の修正:

    - is a predeclared type or a type literal, the corresponding underlying
    + is one of the predeclared boolean, numeric, or string types, or a type literal,
    

    この行が、基底型の定義における最も重要な変更点です。

    • 変更前は「Tが事前宣言された型、または型リテラルである場合」と広範に定義されていました。
    • 変更後は「Tが事前宣言されたbooleannumeric、またはstring型、または型リテラルである場合」と、事前宣言された型をより具体的に限定しています。

この修正により、errorのようなインターフェース型の事前宣言された型は、この限定されたリストから除外され、その基底型が「型宣言で参照する型の基底型」という一般的なルールに従うことになります。これにより、errorの基底型がinterface{ Error() string }であることが明確に示されるようになりました。

関連リンク

  • Go言語の仕様書: https://go.dev/ref/spec (このコミットで変更された内容が反映されています)
  • Go言語の型システムに関する公式ブログ記事やドキュメント(基底型やインターフェースについて解説されているもの)

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語の仕様書(doc/go_spec.htmlの変更履歴)
  • Go言語の型システムに関する一般的な知識