[インデックス 12313] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
に対する軽微な修正と改善を目的としています。具体的には、ポインタ型、関数型、およびシフト演算の例をよりGo言語の慣用的な記述に合わせ、一貫性を向上させています。
コミット
commit 953f2dec8985298ff29bb8a88b8933d34b64db7e
Author: Robert Griesemer <gri@golang.org>
Date: Thu Mar 1 10:35:15 2012 -0800
spec: minor tweaks
- more idiomatic examples of pointer types
- show use of _ in examples of function types
- remove "legal:" qualification in examples
for consistency
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5711054
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/953f2dec8985298ff29bb8a88b8933d34b64db7e
元コミット内容
このコミットの元のメッセージは以下の通りです。
spec: minor tweaks
- more idiomatic examples of pointer types
- show use of _ in examples of function types
- remove "legal:" qualification in examples
for consistency
これは、Go言語の仕様書における以下の3つの主要な変更点を示しています。
- ポインタ型の例をより慣用的なものに変更する。
- 関数型の例でブランク識別子
_
の使用を示す。 - 例における「legal:」という記述を、一貫性のために削除する。
変更の背景
Go言語は、その設計思想として「シンプルさ」と「実用性」を重視しています。言語仕様書は、その言語の振る舞いを正確かつ明確に記述する最も重要なドキュメントです。このコミットは、Go言語の初期段階において、仕様書の記述をより分かりやすく、かつGoの慣用的なスタイルに沿ったものにするための継続的な改善の一環として行われました。
特に、以下の点が背景にあります。
- 学習曲線と理解の促進: 新しいプログラマがGo言語を学ぶ際に、仕様書の例がより実践的で慣用的なものであることで、言語の理解が深まり、正しいコーディングスタイルを身につけやすくなります。
- 一貫性の向上: ドキュメント全体で記述スタイルや用語の使い方が一貫していることは、読者の混乱を防ぎ、情報の信頼性を高めます。
- 言語の成熟: 言語が進化し、コミュニティでの慣用的なパターンが確立されるにつれて、仕様書もそれに合わせて更新される必要があります。
前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語の基本的な概念と、一般的なプログラミングの知識が必要です。
1. Go言語のポインタ (Pointers)
Go言語におけるポインタは、変数のメモリアドレスを指し示す特殊な変数です。C/C++のポインタと似ていますが、ポインタ演算(アドレスの加減算)は許可されておらず、より安全に設計されています。
- 宣言:
var p *int
のように、型名の前に*
を付けて宣言します。これは「p
はint
型の値を指すポインタである」ことを意味します。 - アドレスの取得: 変数のアドレスは
&
演算子を使って取得します。例:p = &x
(変数x
のアドレスをp
に代入)。 - 値の参照(デリファレンス): ポインタが指すメモリアドレスに格納されている値は
*
演算子を使って参照します。例:value = *p
(p
が指す値を取得)。
2. Go言語の関数型 (Function Types)
Go言語では、関数も第一級オブジェクトであり、変数に代入したり、関数の引数として渡したり、関数の戻り値として返すことができます。関数の型は、その関数の引数の型と戻り値の型によって定義されます。
- 宣言:
func(param1_type, param2_type) return_type
の形式で記述されます。- 例:
func(int, string) bool
は、int
とstring
を引数にとり、bool
を返す関数の型です。
- 例:
- 可変長引数:
...
を使用して可変長引数を定義できます。例:func(prefix string, values ...int)
。
3. Go言語のブランク識別子 (Blank Identifier _
)
Go言語のブランク識別子 _
は、値を意図的に破棄するために使用される特別な識別子です。主に以下の状況で利用されます。
- 未使用の変数: Goでは、宣言されたが使用されていない変数はコンパイルエラーになります。しかし、特定の値を無視したい場合(例えば、複数の戻り値を持つ関数で一部の値だけが必要な場合)に
_
を使用することで、エラーを回避できます。- 例:
_, err := someFunction()
- 例:
- インポート: パッケージをインポートする際に、そのパッケージの初期化関数(
init()
)だけを実行したいが、そのパッケージ内の関数や変数を使用しない場合に_
を使用します。- 例:
import _ "github.com/some/package"
- 例:
- インターフェースの実装確認: 型が特定のインターフェースを実装していることをコンパイル時に確認するために使用されることがあります。
- 関数の引数: このコミットで示されているように、関数の引数として
_
を使用することで、その引数がシグネチャ上は必要だが、関数本体では使用しないことを明示できます。これにより、コードの意図が明確になり、未使用変数によるコンパイルエラーを防ぎます。
4. Go言語のシフト演算 (Shift Operations)
Go言語では、ビット単位のシフト演算子 <<
(左シフト) と >>
(右シフト) があります。これらは数値をビット単位で移動させます。
x << n
:x
のビットをn
ビット左にシフトします。これはx * 2^n
と同等です。x >> n
:x
のビットをn
ビット右にシフトします。これはx / 2^n
と同等です(整数除算)。- 定数シフト式: シフト量が定数である場合、コンパイル時に評価されることがあります。
技術的詳細
このコミットは、Go言語の仕様書 doc/go_spec.html
内のコード例を、よりGo言語の慣用的なスタイルに合わせるための具体的な変更を含んでいます。
1. ポインタ型の例の慣用化
変更前は、ポインタ型の例として *int
や *map[string]*chan int
のように、組み込み型へのポインタが示されていました。これらは文法的には正しいですが、Go言語では構造体(struct)などのユーザー定義型へのポインタがより頻繁に使用されます。
変更後は、*Point
や *[4]int
のように、より具体的な型や複合型へのポインタを示すことで、実際のGoコードでポインタがどのように使われるかという文脈をより良く反映しています。Point
は通常、struct
型として定義されることが想定され、*[4]int
は配列へのポインタを示します。これにより、読者はポインタの概念をより実践的な視点から理解できるようになります。
2. 関数型の例におけるブランク識別子 _
の使用
Go言語では、関数の引数や戻り値が使用されない場合に、コンパイラが未使用変数エラーを出すことがあります。これを回避しつつ、関数のシグネチャを維持するために、ブランク識別子 _
が使用されます。
このコミットでは、関数型の例に func(a, _ int, z float32) bool
という形式が追加されました。これは、2番目の int
型の引数がシグネチャ上は存在するものの、関数本体ではその値が使用されないことを明示しています。これはGoのコードベースで頻繁に見られるイディオムであり、仕様書に含めることで、この慣用的な使い方を公式に示し、読者に推奨するものです。
3. 例における「legal:」修飾子の削除
Go言語の仕様書では、コード例が文法的に正しいかどうかを示すために「legal:」という修飾子が使われている箇所がありました。しかし、これは冗長であり、他の例との一貫性を損ねる可能性がありました。
このコミットでは、var m int = 1.0<<s // legal: 1.0 has type int
のような行から「legal:」という記述が削除されました。これにより、例の記述が簡潔になり、ドキュメント全体での表現の一貫性が向上します。仕様書内の例は、特に断りがない限り、文法的に正しいものであることが前提であるため、この修飾子は不要と判断されたと考えられます。
コアとなるコードの変更箇所
変更は doc/go_spec.html
ファイルに対して行われました。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{\n \t\"Title\": \"The Go Programming Language Specification\",\n-\t\"Subtitle\": \"Version of February 29, 2012\"\n+\t\"Subtitle\": \"Version of March 1, 2012\"\n }-->
\n <!--\n@@ -1007,8 +1007,8 @@ BaseType = Type .\n </pre>\n \n <pre>\n-*int
-*map[string]*chan int
+*Point
+*[4]int
</pre>\n \n <h3 id=\"Function_types\">Function types</h3>\n@@ -1046,11 +1046,10 @@ may be invoked with zero or more arguments for that parameter.\n \n <pre>\n func()\n-func(x int)\n-func() int
-func(prefix string, values ...int)\n-func(a, b int, z float32) bool
+func(x int) int
+func(a, _ int, z float32) bool
func(a, b int, z float32) (bool)\n+func(prefix string, values ...int)\n func(a, b int, z float64, opt ...interface{}) (success bool)\n func(int, int, float64) (float64, *[]int)\n func(n int) func(p *T)\n@@ -2788,13 +2787,13 @@ var s uint = 33\n var i = 1<<s // 1 has type int\n var j int32 = 1<<s // 1 has type int32; j == 0\n var k = uint64(1<<s) // 1 has type uint64; k == 1<<33\n-var m int = 1.0<<s // legal: 1.0 has type int\n-var n = 1.0<<s != 0 // legal: 1.0 has type int; n == false if ints are 32bits in size\n-var o = 1<<s == 2<<s // legal: 1 and 2 have type int; o == true if ints are 32bits in size\n+var m int = 1.0<<s // 1.0 has type int\n+var n = 1.0<<s != 0 // 1.0 has type int; n == false if ints are 32bits in size\n+var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size\n var p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int\n var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift\n var v float32 = 1<<s // illegal: 1 has type float32, cannot shift\n-var w int64 = 1.0<<33 // legal: 1.0<<33 is a constant shift expression\n+var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression\n```
## コアとなるコードの解説
上記の差分から、以下の具体的な変更点とその意図が読み取れます。
1. **仕様書の日付更新**:
* `- \t"Subtitle": "Version of February 29, 2012"`
* `+ \t"Subtitle": "Version of March 1, 2012"`
* これは、コミットが適用された日付に合わせて仕様書のバージョン表記を更新したものです。
2. **ポインタ型の例の変更**:
* `- *int`
* `- *map[string]*chan int`
* `+ *Point`
* `+ *[4]int`
* `*int` や `*map[string]*chan int` のような抽象的な組み込み型へのポインタの例が削除され、代わりに `*Point` (ユーザー定義の構造体などへのポインタを想定) や `*[4]int` (配列へのポインタ) といった、より具体的でGo言語の慣用的なポインタの使用例が追加されました。これにより、読者はポインタが実際のコードでどのように使われるかをより直感的に理解できます。
3. **関数型の例の変更と追加**:
* `- func(x int)`
* `- func() int`
* `- func(prefix string, values ...int)`
* `- func(a, b int, z float32) bool`
* `+ func(x int) int`
* `+ func(a, _ int, z float32) bool`
* `+ func(prefix string, values ...int)` (位置が移動)
* いくつかの既存の関数型の例が削除または変更され、特に `func(a, _ int, z float32) bool` という新しい例が追加されました。この変更の最も重要な点は、ブランク識別子 `_` を関数の引数として使用するGoの慣用的なパターンを示すことです。これは、引数がシグネチャ上は必要だが、関数本体では使用されない場合に、未使用変数エラーを回避しつつコードの意図を明確にするために使われます。また、`func(prefix string, values ...int)` の位置が移動し、より自然な流れになるように調整されています。
4. **シフト演算の例における「legal:」修飾子の削除**:
* `- var m int = 1.0<<s // legal: 1.0 has type int`
* `- var n = 1.0<<s != 0 // legal: 1.0 has type int; n == false if ints are 32bits in size`
* `- var o = 1<<s == 2<<s // legal: 1 and 2 have type int; o == true if ints are 32bits in size`
* `- var w int64 = 1.0<<33 // legal: 1.0<<33 is a constant shift expression`
* `+ var m int = 1.0<<s // 1.0 has type int`
* `+ var n = 1.0<<s != 0 // 1.0 has type int; n == false if ints are 32bits in size`
* `+ var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size`
* `+ var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression`
* シフト演算の例において、コメント内の「legal:」という記述が削除されました。これは、仕様書内の例は特に断りがない限り文法的に正しいものであるという前提に基づき、冗長な表現を排除し、ドキュメント全体の一貫性を高めるための変更です。
これらの変更は全体として、Go言語の仕様書をより明確で、慣用的で、一貫性のあるものにすることを目的としています。
## 関連リンク
* **Go Change List (CL)**: [https://golang.org/cl/5711054](https://golang.org/cl/5711054)
* このリンクは、GoプロジェクトのコードレビューシステムであるGerritにおける、このコミットに対応する変更リスト(Change List)を示しています。ここには、コミットに至るまでの議論やレビューコメントが含まれている場合があります。
## 参考にした情報源リンク
* **The Go Programming Language Specification**: [https://go.dev/ref/spec](https://go.dev/ref/spec)
* このコミットが修正対象としているGo言語の公式仕様書です。
* **Effective Go**: [https://go.dev/doc/effective_go](https://go.dev/doc/effective_go)
* Go言語の慣用的なプログラミングスタイルやベストプラクティスについて解説している公式ドキュメントです。ブランク識別子やポインタの慣用的な使用法について、より深い理解を得るのに役立ちます。
* **A Tour of Go**: [https://go.dev/tour/](https://go.dev/tour/)
* Go言語の基本的な概念をインタラクティブに学べるチュートリアルです。ポインタや関数型などの基礎知識を復習するのに適しています。