[インデックス 10612] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
ファイルに対する変更です。このファイルは、Go言語の構文、セマンティクス、および標準ライブラリの動作を定義する、開発者にとって最も重要なドキュメントの一つです。
コミット
このコミットは、Go言語の仕様から「複合リテラルの短縮形(elision)」に関する特定のルール、特に構造体リテラル内のフィールド値に対する短縮形の使用を削除するものです。これは、その機能が「議論の的(contentious)」であったため、仕様から取り除かれました。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/98553f1422392f135989e0daafab352b66c561c2
元コミット内容
commit 98553f1422392f135989e0daafab352b66c561c2
Author: Russ Cox <rsc@golang.org>
Date: Mon Dec 5 14:22:23 2011 -0500
spec: remove contentious composite literal shortening
R=gri, r, gustavo, r
CC=golang-dev
https://golang.org/cl/5451099
変更の背景
この変更の背景には、Go言語の複合リテラルにおける「短縮形(elision)」の特定の形式、特に構造体リテラル内でネストされた複合リテラルの型を省略する機能が、コミュニティ内で議論の対象となっていたという経緯があります。
Go言語の設計哲学の一つに「明示的であること」があります。しかし、この短縮形は、コードの簡潔さを追求する一方で、可読性や意図の明確さを損なう可能性があると見なされていました。特に、ネストが深くなるにつれて、省略された型を推論することが難しくなり、コードの理解を妨げるという懸念が表明されていました。
このコミットは、Go言語の設計者の一人であるRuss Coxによって行われ、Go言語の仕様をより明確で、曖昧さの少ないものにするための継続的な取り組みの一環として、この「議論の的となる」機能を仕様から削除する決定が下されました。これにより、言語の学習曲線が緩やかになり、予期せぬ挙動を避けることが目的とされました。
前提知識の解説
複合リテラル (Composite Literals)
Go言語における複合リテラルは、構造体(struct)、配列(array)、スライス(slice)、マップ(map)などの複合型を初期化するための構文です。これにより、変数の宣言と同時にその値を設定することができます。
例:
- 構造体リテラル:
Point{X: 10, Y: 20}
- 配列リテラル:
[3]int{1, 2, 3}
- スライスリテラル:
[]string{"a", "b", "c"}
- マップリテラル:
map[string]int{"apple": 1, "banana": 2}
型の省略 (Type Elision)
Goの複合リテラルでは、特定の状況下で型の記述を省略できる「型の省略(type elision)」という機能があります。これは、コンパイラが文脈から型を推論できる場合に適用されます。
例:
[][]int{{1, 2, 3}, {4, 5}}
これは、[][]int{[]int{1, 2, 3}, []int{4, 5}}
と同じ意味です。内側のスライスリテラル []int
の型が、外側のスライス [][]int
の要素型から推論できるため、省略されています。
ポインタと複合リテラル
Goでは、複合リテラルの前に &
を付けることで、そのリテラルが指す値へのポインタを作成できます。
例: &Point{X: 1, Y: 2}
は Point{X: 1, Y: 2}
という構造体のインスタンスを作成し、そのインスタンスへのポインタを返します。
議論の的となった短縮形
このコミットで削除されたのは、特に構造体リテラル内で、ネストされた構造体リテラルがポインタ型である場合に、そのポインタと型を省略できるという短縮形でした。
具体的には、以下のようなコードが許容されていました。
type List struct {
Val int
Next *List
}
// 削除された短縮形:
&List{Val: 1, Next: {Val: 2}}
これは、以下のように展開されると解釈されていました。
// 展開された形:
&List{Val: 1, Next: &List{Val: 2}}
Next: {Val: 2}
の部分で、Next
フィールドが *List
型であるため、{Val: 2}
が &List{Val: 2}
と自動的に解釈されるというルールでした。この「自動的なポインタと型の挿入」が、コードの意図を不明瞭にし、混乱を招く可能性があるとして問題視されました。
技術的詳細
このコミットは、Go言語の仕様書 doc/go_spec.html
から、複合リテラルにおける特定の型の省略ルールを削除しました。具体的には、以下の記述が削除されました。
The same elisions may be applied to field values within a struct literal,
but only if the value has a field name key.
この記述は、「構造体リテラル内のフィールド値に対しても、同じ省略(elision)が適用されるが、それはフィールド名キーを持つ値に限る」というルールを説明していました。このルールが削除されたことにより、構造体リテラルのフィールド値において、ネストされた複合リテラルの型やポインタを自動的に省略する挙動が、Go言語の仕様上は許容されなくなりました。
また、このルールを説明するための具体的なコード例も削除されました。
type List struct {
Val int
Next *List
}
&List{Val: 1, Next: {Val: 2}} // same as &List{Val: 1, Next: &List{Val: 2}}
この例は、Next
フィールドが *List
型であるため、Next: {Val: 2}
が Next: &List{Val: 2}
と解釈されることを示していました。この短縮形が仕様から削除されたことで、今後はこのような記述はコンパイルエラーとなるか、あるいは異なる意味を持つことになります(Go 1以降では、この短縮形は許可されていません)。
この変更は、Go言語の構文解析器やコンパイラの挙動にも影響を与え、より厳密な型指定が求められるようになりました。これにより、コードの意図がより明確になり、潜在的なバグや誤解を減らすことが期待されます。
コアとなるコードの変更箇所
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of December 2, 2011 -->
+<!-- subtitle Version of December 5, 2011 -->
<!--
TODO
@@ -2120,8 +2120,6 @@ elements that are themselves composite literals may elide the respective
literal type if it is identical to the element type of <code>T</code>.\n Similarly, elements that are addresses of composite literals may elide\n the <code>&T</code> when the the element type is <code>*T</code>.\n-The same elisions may be applied to field values within a struct literal,\n-but only if the value has a field name key.\n </p>\n \n \n@@ -2131,13 +2129,6 @@ but only if the value has a field name key.\n [][]int{{1, 2, 3}, {4, 5}} // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}\n \n [...]*Point{{1.5, -3.5}, {0, 0}} // same as [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}\n-\n-type List struct {\n-\tVal int\n-\tNext *List\n-}\n-\n-&List{Val: 1, Next: {Val: 2}} // same as &List{Val: 1, Next: &List{Val: 2}}\n </pre>\n \n <p>\n```
## コアとなるコードの解説
上記のdiffは、`doc/go_spec.html` ファイルから以下の2つの主要な変更点を示しています。
1. **仕様記述の削除**:
```html
-The same elisions may be applied to field values within a struct literal,
-but only if the value has a field name key.
```
この2行は、構造体リテラル内のフィールド値に対する型の省略(elision)に関するルールを記述していました。このルールが削除されたことで、Go言語の仕様において、構造体リテラルのフィールド値で型を省略する特定の形式が許可されなくなりました。特に、ネストされた複合リテラルがポインタ型である場合に、そのポインタと型を自動的に推論して省略する挙動が対象です。
2. **コード例の削除**:
```go
-type List struct {
- Val int
- Next *List
-}
-
-&List{Val: 1, Next: {Val: 2}} // same as &List{Val: 1, Next: &List{Val: 2}}
```
このコードブロックは、削除された仕様ルールを具体的に示す例でした。`&List{Val: 1, Next: {Val: 2}}` という記述が、`&List{Val: 1, Next: &List{Val: 2}}` と同じ意味を持つことを示していました。この例が削除されたことは、この短縮形がもはやGo言語の有効な構文ではないことを意味します。
これらの変更は、Go言語の仕様をより厳密にし、曖昧さを排除することを目的としています。これにより、開発者はコードの意図をより明確に記述する必要があり、コンパイラもより予測可能な挙動を示すようになります。結果として、Go言語のコードはより読みやすく、理解しやすくなることが期待されます。
## 関連リンク
* Go Change List: [https://golang.org/cl/5451099](https://golang.org/cl/5451099)
## 参考にした情報源リンク
* Go Programming Language Specification: [https://go.dev/ref/spec](https://go.dev/ref/spec) (現在の仕様)
* Go言語の複合リテラルに関する議論(当時のメーリングリストなど、具体的なリンクはコミット情報からは直接辿れませんが、`golang-dev` CCから当時の議論が存在したことが示唆されます。)
* Go言語の歴史と設計哲学に関するドキュメントやブログ記事。