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

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

このコミットは、Go言語の標準ライブラリの一部である src/pkg/builtin/builtin.go ファイルに対して行われた変更を記録しています。この変更の主な目的は、Go言語の組み込み(基本)型(bool, uint8, int, float32, string など)に関するドキュメントを godoc ツールが適切に生成できるように、これらの型を明示的に定義し、詳細なコメントを追加することです。

コミット

  • コミットハッシュ: 7db617b4747342e48d2f6586dacecd31511f365a
  • 作者: Rob Pike r@golang.org
  • コミット日時: 2011年11月2日 水曜日 12:06:36 -0700

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

https://github.com/golang/go/commit/7db617b4747342e48d2f6586dacecd31511f365a

元コミット内容

builtin: document the basic types
The recursive definitions are illegal Go, but godoc doesn't mind.

R=bradfitz, r, n13m3y3r, rsc
CC=golang-dev
https://golang.org/cl/5322067

変更の背景

Go言語には、bool, int, string などの基本的な組み込み型が多数存在します。これらの型は言語の根幹をなすものであり、その特性や使用方法に関する正確なドキュメントが不可欠です。Go言語のドキュメンテーションツールである godoc は、ソースコード内のコメントや宣言から自動的にドキュメントを生成します。

このコミットが行われた当時、godoc がこれらの組み込み型に関する詳細な情報を適切に表示するためのメカニズムが不足していた可能性があります。特に、型の範囲や特性といった情報は、単に型が存在するだけでは godoc には伝わりません。

コミットメッセージにある「The recursive definitions are illegal Go, but godoc doesn't mind.」という記述は、この変更の核心を示しています。Go言語の文法上、type T T のような再帰的な型定義は通常は許可されません。しかし、godoc はこの特殊な形式を、組み込み型に対するドキュメンテーションコメントを関連付けるための「フック」として利用できるように設計されていました。これにより、コンパイラは無視するが godoc は読み取る、という形で、組み込み型に詳細な説明を追加することが可能になりました。

この変更の目的は、Go言語の公式ドキュメント(特に godoc を通じて提供されるもの)の品質と網羅性を向上させ、開発者が組み込み型についてより深く理解できるようにすることでした。

前提知識の解説

Go言語の基本的な型

Go言語は、静的型付け言語であり、以下のような基本的な組み込み型を提供します。

  • ブーリアン型: bool (true または false)
  • 数値型:
    • 符号付き整数型: int8, int16, int32, int64, int (アーキテクチャ依存のサイズ)
    • 符号なし整数型: uint8, uint16, uint32, uint64, uint (アーキテクチャ依存のサイズ), uintptr (ポインタを保持できるサイズ)
    • 浮動小数点型: float32, float64 (IEEE-754 形式)
    • 複素数型: complex64 (float32 の実部と虚部), complex128 (float64 の実部と虚部)
  • 文字列型: string (UTF-8 エンコードされたバイト列の不変シーケンス)
  • バイト型: byte ( uint8 のエイリアス)
  • ルーン型: rune ( int32 のエイリアスで、Unicode コードポイントを表す)

これらの型は、Goプログラムの基本的な構成要素であり、それぞれの型には特定のメモリ表現と操作が定義されています。

godoc ツールとその役割

godoc は、Go言語のソースコードからドキュメントを生成するための公式ツールです。Goの設計思想の一つに「ドキュメントはコードの近くにあるべき」というものがあり、godoc はこの原則を具現化しています。

godoc は以下の特徴を持ちます。

  • 自動生成: ソースコード内のパッケージ、関数、型、変数、定数などの宣言と、それらに付随するコメントを解析し、HTML形式のドキュメントを自動生成します。
  • コメントの重要性: godoc は、宣言の直前にあるコメントをその宣言のドキュメントとして扱います。特に、エクスポートされた(大文字で始まる)識別子に対するコメントは重要です。
  • ローカルでの利用: godoc コマンドを実行すると、ローカルマシン上でGoの標準ライブラリやGOPATH内のプロジェクトのドキュメントをブラウザで閲覧できるWebサーバーを起動できます。
  • golang.org/pkg: 公式サイト golang.org/pkg で提供されている標準ライブラリのドキュメントは、godoc ツールによって生成されたものです。

Go言語における型定義 (type NewType OldType) とその通常の用途

Go言語では、type キーワードを使用して新しい型を定義できます。最も一般的な形式は、既存の型を基にした新しい型の宣言です。

type MyInt int
type Celsius float64

この場合、MyIntint とは異なる新しい型であり、Celsiusfloat64 とは異なる新しい型です。これにより、型安全性を高めたり、特定の意味を持つ型を導入したりできます。例えば、Celsius 型の変数に Fahrenheit 型の値を直接代入することはできません。

"recursive definitions are illegal Go" の意味

Go言語の型システムでは、通常、型が自分自身を直接的に参照するような再帰的な型定義は許可されません。例えば、以下のようなコードはコンパイルエラーになります。

// これはGo言語では不正なコードです
type MyType MyType

このような定義は無限の再帰を引き起こし、型のサイズを決定できないため、コンパイラはこれを拒否します。しかし、このコミットでは type bool bool のような形式が使用されています。これは、通常のGoプログラムのコンテキストでは不正ですが、godoc がドキュメント生成のために特別に解釈する「抜け道」として利用されています。godoc はコンパイラとは異なり、この形式を「組み込み型 bool のドキュメントをここに記述する」という指示として認識します。

技術的詳細

このコミットの技術的な核心は、src/pkg/builtin/builtin.go ファイル内で、Go言語の組み込み型に対して「再帰的な型定義」の形式 (type T T) を用いてドキュメントコメントを付与している点にあります。

src/pkg/builtin/builtin.go ファイルの役割

src/pkg/builtin/builtin.go は、Go言語のコンパイラが認識する組み込み型や組み込み関数(len, cap, make, new, append, panic, recover など)の「宣言」を godoc のために提供する特殊なファイルです。これらの組み込み要素は、言語仕様の一部としてコンパイラに直接組み込まれており、通常のGoパッケージのようにインポートされるわけではありません。しかし、godoc がこれらの要素に関するドキュメントを生成するためには、何らかの形でそれらの「宣言」とコメントが存在する必要があります。このファイルは、そのためのプレースホルダーとして機能します。

type T T 形式の型定義がGo言語のコンパイラではエラーとなるが、godoc がこれをどのように解釈し、ドキュメント生成に利用するか

前述の通り、type T T はGo言語のコンパイラにとっては不正な再帰的型定義です。しかし、godoc はこのパターンを特別に扱います。godoc は、この形式の宣言を見つけると、それがGo言語の組み込み型 T のドキュメントを記述するためのものであると解釈します。そして、その宣言の直前にあるコメントを、組み込み型 T の公式ドキュメントとして取り込みます。

これにより、Go言語のソースコード自体には存在しない(コンパイラが直接扱う)組み込み型に対して、あたかも通常の型であるかのように詳細な説明を付与し、godoc を通じて公開することが可能になります。これは、Go言語のドキュメンテーションシステムが、言語の内部構造と外部ドキュメントの間のギャップを埋めるための巧妙なメカニズムです。

各基本型に対するコメントの内容

コミットで追加されたコメントは、各組み込み型の重要な特性を簡潔かつ正確に記述しています。

  • 数値型: uint8, uint16, uint32, uint64, int8, int16, int32, int64 については、それぞれのビット数と、表現できる値の範囲が明記されています。float32float64 については、IEEE-754 形式であることが示されています。
  • string: 「8ビットバイトの文字列の集合であり、慣習的にUTF-8エンコードされたテキストを表すが、必ずしもそうではない」「空にできるが、nil にはできない」「値は不変である」といった重要な特性が説明されています。
  • int, uint: 「少なくとも32ビットサイズの符号付き/符号なし整数型である」「int32 のようなエイリアスではない、独立した型である」という点が強調されています。これは、intuint のサイズがコンパイル環境によって異なる可能性があることを示唆しています。
  • uintptr: 「任意のポインタのビットパターンを保持するのに十分な大きさの整数型である」と説明されています。
  • byte, rune: それぞれ uint8int32 のエイリアスであり、慣習的にバイト値と文字値を区別するために使用されることが明記されています。特に rune については、「将来のGoのバージョンでは int32 のエイリアスに変更される」という将来の変更に関する言及も含まれています(実際にはGo 1.0のリリース時には runeint32 のエイリアスとして定義されました)。

これらのコメントは、Go言語の型システムを理解する上で非常に重要な情報を提供しています。

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

src/pkg/builtin/builtin.go ファイルにおける変更の差分は以下の通りです。

--- a/src/pkg/builtin/builtin.go
+++ b/src/pkg/builtin/builtin.go
@@ -10,6 +10,82 @@
 */
 package builtin
 
+// bool is the set of boolean values, true and false.
+type bool bool
+
+// uint8 is the set of all unsigned  8-bit integers.
+// Range: 0 through 255.
+type uint8 uint8
+
+// uint16 is the set of all unsigned 16-bit integers.
+// Range: 0 through 65535.
+type uint16 uint16
+
+// uint32 is the set of all unsigned 32-bit integers.
+// Range: 0 through 4294967295.
+type uint32 uint32
+
+// uint64 is the set of all unsigned 64-bit integers.
+// Range: 0 through 18446744073709551615.
+type uint64 uint64
+
+// int8 is the set of all signed  8-bit integers.
+// Range: -128 through 127.
+type int8 int8
+
+// int16 is the set of all signed 16-bit integers.
+// Range: -32768 through 32767.
+type int16 int16
+
+// int32 is the set of all signed 32-bit integers.
+// Range: -2147483648 through 2147483647.
+type int32 int32
+
+// int64 is the set of all signed 64-bit integers.
+// Range: -9223372036854775808 through 9223372036854775807.
+type int64 int64
+
+// float32 is the set of all IEEE-754 32-bit floating-point numbers.
+type float32 float32
+
+// float64 is the set of all IEEE-754 64-bit floating-point numbers.
+type float64 float64
+
+// complex64 is the set of all complex numbers with float32 real and
+// imaginary parts.
+type complex64 complex64
+
+// complex128 is the set of all complex numbers with float64 real and
+// imaginary parts.
+type complex128 complex128
+
+// string is the set of all strings of 8-bit bytes, conventionally but not
+// necessarily representing UTF-8-encoded text. A string may be empty, but
+// not nil. Values of string type are immutable.
+type string string
+
+// int is a signed integer type that is at least 32 bits in size. It is a
+// distinct type, however, and not an alias for, say, int32.
+type int int
+
+// uint is an unsigned integer type that is at least 32 bits in size. It is a
+// distinct type, however, and not an alias for, say, uint32.
+type uint uint
+
+// uintptr is an integer type that is large enough to hold the bit pattern of
+// any pointer.
+type uintptr uintptr
+
+// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
+// used, by convention, to distinguish byte values from 8-bit unsigned
+// integer values.
+type byte byte
+
+// rune is an alias for int and is equivalent to int in all ways. It is
+// used, by convention, to distinguish character values from integer values.
+// In a future version of Go, it will change to an alias of int32.
+type rune rune
+
 // Type is here for the purposes of documentation only. It is a stand-in
 // for any Go type, but represents the same type for any given function
 // invocation.
@@ -21,11 +97,11 @@ type IntegerType int
 
 // FloatType is here for the purposes of documentation only. It is a stand-in
 // for either float type: float32 or float64.
-type FloatType int
+type FloatType float32
 
 // ComplexType is here for the purposes of documentation only. It is a
 // stand-in for either complex type: complex64 or complex128.
-type ComplexType int
+type ComplexType complex64
 
 // The append built-in function appends elements to the end of a slice. If
 // it has sufficient capacity, the destination is resliced to accommodate the

コアとなるコードの解説

このコミットでは、主に以下の2種類の変更が行われています。

  1. 組み込み型に対する type T T 形式の宣言とコメントの追加: bool, uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64, complex64, complex128, string, int, uint, uintptr, byte, rune といったGo言語の組み込み型それぞれに対して、以下のような形式のコードが追加されています。

    // <型に関する詳細な説明コメント>
    type <型名> <型名>
    

    例えば、bool 型の場合:

    // bool is the set of boolean values, true and false.
    type bool bool
    

    この type bool bool という宣言は、Goコンパイラにとっては無意味または不正な再帰的定義ですが、godoc ツールはこれを bool 型のドキュメントを生成するためのマーカーとして認識します。その直前のコメント行が、godoc によって bool 型の公式ドキュメントとして取り込まれ、golang.org/pkg/builtin などで閲覧できるようになります。これにより、各組み込み型の特性(例:uint8 の範囲、string の不変性)が明確にドキュメント化されます。

  2. FloatType および ComplexType の基底型の変更: 既存の FloatTypeComplexType の定義が変更されています。

    変更前:

    type FloatType int
    type ComplexType int
    

    変更後:

    type FloatType float32
    type ComplexType complex64
    

    これらの型は、コメントにもあるように「ドキュメンテーション目的のみ」の型であり、float32 または float64complex64 または complex128 のいずれかの型を表すためのプレースホルダーとして機能します。変更前は基底型が int でしたが、変更後はそれぞれ float32complex64 になっています。これは、これらの型が実際に浮動小数点数や複素数を表すことをより正確に反映させるための変更と考えられます。godoc がこれらの型を処理する際に、より適切な型情報として解釈されることを意図している可能性があります。

このコミット全体として、Go言語の組み込み型に関するドキュメントの質を向上させ、godoc がより正確で詳細な情報を生成できるようにするための、特殊ながらも効果的なアプローチが取られています。

関連リンク

  • Go CL 5322067: https://golang.org/cl/5322067 - このコミットに対応するGoのコードレビューシステム(Gerrit)のチェンジリスト。詳細な議論やレビューコメントが確認できます。
  • Go言語の公式ドキュメント (builtinパッケージ): https://pkg.go.dev/builtin - このコミットによって追加されたドキュメントが実際に反映されている場所です。

参考にした情報源リンク