[インデックス 1637] ファイルの概要
このコミットは、Goプログラミング言語の初期の仕様書である doc/go_spec.txt
に対する変更を記録しています。主な目的は、関数リテラル(クロージャ)に関する記述の修正と明確化、および仕様書内の誤字修正やTODOリストの更新です。特に、関数リテラルがクロージャとして振る舞うことに関する実装上の制限を削除し、その挙動を明示的に定義した点が重要です。
コミット
commit d8a764cc7eb4e1919c152a4a121bd0585d4428ac
Author: Robert Griesemer <gri@golang.org>
Date: Fri Feb 6 17:01:10 2009 -0800
- removed todo and restriction from spec (closures)
- fixed typos, added a reminder for a todo
R=r
DELTA=23 (6 added, 4 deleted, 13 changed)
OCL=24611
CL=24615
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d8a764cc7eb4e1919c152a4a121bd0585d4428ac
元コミット内容
このコミットは、Go言語の仕様書 doc/go_spec.txt
に対して以下の変更を行っています。
- TODOリストの更新:
- 新しいTODO項目として「
;
と空のステートメント、ラベル宣言に関する奇妙な点」を追加。 - 以前のTODO項目「関数型に
func
を再導入すること、関数リテラルをスライスのように振る舞わせること、関数値を取得する際に&
を不要にすること」を完了済みとしてマーク。これはRuss Cox氏からの提案でした。
- 新しいTODO項目として「
- 関数リテラル(クロージャ)の仕様変更:
- 最も重要な変更点として、関数リテラルに関する「実装上の制限」を削除。この制限は、「関数リテラルは、そのパラメータ、グローバル変数、および関数リテラル内で宣言された変数のみを参照できる」というものでした。
- この制限の削除と同時に、関数リテラルが「クロージャ」であるという明確な定義を追加。「関数リテラルは、囲む関数で定義された変数を参照できる。これらの変数は、囲む関数と関数リテラルの間で共有され、アクセス可能な限り存続する」と記述されました。
- 用語の修正:
- 「Composite Literals」を「Composite literals」に、「Function Literals」を「Function literals」に修正(大文字から小文字へ)。
- 誤字修正:
- インターフェースに関する記述で「interface M」を「method M」に修正。
- 初期化コードの実行順序に関する明確化:
go
ステートメントによって呼び出される関数が、プログラム全体の初期化が完了するまで実行を開始しないことを明確化。これにより、すべての初期化コードが単一のスレッドで実行されることが保証されます。
- 日付の更新:
- 仕様書の日付を「February 5, 2009」から「February 6, 2009」に更新。
変更の背景
このコミットは、Go言語がまだ開発の初期段階にあった2009年2月に行われたものです。Go言語は2009年11月に一般公開されるため、この時期は言語の核となる設計と仕様が活発に議論され、固められていた時期にあたります。
特に、関数リテラル(クロージャ)に関する変更は、Go言語の設計思想における重要な決定を反映しています。初期の仕様では、関数リテラルが参照できる変数に「実装上の制限」が設けられていましたが、これはクロージャの本来の強力な機能(囲むスコープの変数をキャプチャし、そのライフサイクルを延長する能力)を制限するものでした。このコミットによってその制限が撤廃され、Goの関数リテラルが真のクロージャとして機能することが明確にされました。これは、Goが関数型プログラミングのパラダイムを取り入れ、より柔軟で表現力豊かなコード記述を可能にする上で不可欠なステップでした。
また、仕様書内の誤字修正やTODOリストの整理は、言語仕様の正確性と完成度を高めるための継続的な取り組みの一環です。初期化コードの実行順序に関する明確化も、並行処理を重視するGo言語において、プログラムの挙動を予測可能にするための重要な改善です。
前提知識の解説
このコミットの理解には、以下の概念が役立ちます。
- Go言語 (Golang): Googleで開発された静的型付けのコンパイル型プログラミング言語。シンプルさ、効率性、並行処理のサポートを重視しています。2009年11月に一般公開されました。
- 関数リテラル (Function Literals): Go言語における匿名関数(名前を持たない関数)のこと。コード内で直接定義され、変数に代入したり、関数の引数として渡したり、戻り値として返したりすることができます。
- クロージャ (Closures): 関数リテラルが持つ特性の一つで、関数が定義された環境(囲むスコープ)の変数を「記憶」し、その関数がそのスコープ外で実行された際にもそれらの変数にアクセスできる機能です。これにより、関数が特定の状態を保持できるようになります。クロージャは、状態のカプセル化、高階関数、遅延実行などのパターンを可能にします。
- Go言語の仕様書 (Go Programming Language Specification): Go言語の構文、セマンティクス、標準ライブラリの動作などを定義する公式文書。言語の設計と実装の基盤となります。
go
ステートメント: Go言語におけるゴルーチン(軽量スレッド)を起動するためのキーワード。go
の後に続く関数呼び出しを新しいゴルーチンで並行して実行します。- 初期化 (Initialization): Goプログラムが実行される前に、パッケージレベルの変数や
init()
関数が実行されるプロセス。このプロセスは、プログラムの起動時に必要なセットアップを行います。
技術的詳細
このコミットの技術的詳細の核心は、Go言語におけるクロージャのセマンティクスが初期段階でどのように確立されたかという点にあります。
-
「実装上の制限」の撤廃: 変更前の仕様では、関数リテラルが参照できる変数の範囲が厳しく制限されていました。これは、クロージャの実装が複雑であること、あるいは初期の設計段階でその挙動が完全に固まっていなかったことを示唆しています。この制限が撤廃されたことで、Goの関数リテラルは、他の多くの現代的な言語(JavaScript、Pythonなど)と同様に、定義されたスコープ内の非ローカル変数を自由にキャプチャできるようになりました。
-
クロージャの明確な定義: 制限の撤廃と同時に、「Function literals are "closures": they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible in any way.」という記述が追加されました。これは、Goのクロージャが「参照渡し」のような形で外部変数をキャプチャし、その変数のライフサイクルがクロージャの存続期間に依存することを明確にしています。つまり、囲む関数の実行が終了しても、クロージャがその変数を参照し続ける限り、その変数はガベージコレクションされずにメモリ上に保持されます。これは、状態をカプセル化したり、コールバック関数で特定のコンテキストを保持したりする際に非常に強力な機能となります。
-
初期化コードの実行順序:
go
ステートメントで起動されるゴルーチンが「プログラム全体の初期化が完了するまで実行を開始しない」という明確化は、Goの並行処理モデルにおける重要な保証です。これにより、初期化フェーズ中に競合状態が発生するのを防ぎ、プログラムが予測可能な状態で起動することを保証します。すべてのinit()
関数とパッケージレベルの変数の初期化が完了してから初めて、go
ステートメントによって起動されたゴルーチンが実行を開始します。これは、Goの設計哲学である「シンプルさと安全性」を反映したものです。 -
用語の統一: 「Composite Literals」や「Function Literals」の「Literals」を小文字に統一した変更は、Go言語の仕様書全体での用語の一貫性を保つための細かながら重要な改善です。これは、公式文書の品質と読みやすさに貢献します。
これらの変更は、Go言語がその後の成功を収める上で不可欠な、堅牢で一貫性のある言語セマンティクスを確立する上で重要な役割を果たしました。
コアとなるコードの変更箇所
変更はすべて doc/go_spec.txt
ファイル内で行われています。
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -3,7 +3,7 @@ The Go Programming Language Specification (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson
-(February 5, 2009)
+(February 6, 2009)
----
@@ -37,6 +37,7 @@ Decisions in need of integration into the doc:
Todo's:
+[ ] there is some funny-ness regarding ';' and empty statements and label decls
[ ] document illegality of package-external tuple assignments to structs
w/ private fields: P.T{1, 2} illegal since same as P.T{a: 1, b: 2} for
a T struct { a b int }.
@@ -68,13 +69,13 @@ Smaller issues:
ta for loop that is following, and can break L be used inside it?
[ ] Russ: If we use x.(T) for all conversions, we could use T() for "construction"
and type literals - would resolve the parsing ambiguity of T{} in if's
-[ ] Russ: consider re-introducing "func" for function type. Make function literals
- behave like slices, etc. Require no &'s to get a function value (solves issue
- of func{} vs &func{} vs &func_name).
-
+-[ ] Russ: consider re-introducing "func" for function type. Make function literals
+- behave like slices, etc. Require no &'s to get a function value (solves issue
+- of func{} vs &func{} vs &func_name).
+
Closed:
+[x] Russ: consider re-introducing "func" for function type. Make function literals
+\tbehave like slices, etc. Require no &'s to get a function value (solves issue
+\tof func{} vs &func{} vs &func_name).
[x] onreturn/undo statement - now: defer statement
[x] comparison of non-basic types: what do we allow? what do we allow in interfaces
what about maps (require ==, copy and hash)
@@ -203,8 +204,8 @@ Contents
Operands
Constants
Qualified identifiers
-- Composite Literals
-- Function Literals
++ Composite literals
++ Function literals
Primary expressions
Selectors
@@ -1794,7 +1795,7 @@ TODO(gri) expand this section.
PackageName = identifier .
-Composite Literals
+Composite literals
----
Literals for composite data structures consist of the type of the value
@@ -1852,7 +1853,7 @@ TODO: Consider adding helper syntax for nested composites
(avoids repeating types but complicates the spec needlessly.)
-Function Literals
+Function literals
----
A function literal represents an anonymous function. It consists of a
@@ -1872,9 +1873,10 @@ corresponding function type, or invoked directly.
f := func(x, y int) int { return x + y; }
func(ch chan int) { ch <- ACK; } (reply_chan)
-Implementation restriction: A function literal can reference only
-its parameters, global variables, and variables declared within the
-function literal.
+Function literals are "closures": they may refer to variables
+defined in a surrounding function. Those variables are then shared between
+the surrounding function and the function literal, and they survive as long
+as they are accessible in any way.
Primary expressions
@@ -2418,7 +2420,7 @@ denotes a method: Effect is as described above, converts into function.\n \n If T is an interface type, the expression t.M does not determine which\n underlying type's M is called until the point of the call itself. Thus given\n-T1 and T2, both implementing interface I with interface M, the sequence\n+T1 and T2, both implementing interface I with method M, the sequence\n \n \tvar t1 *T1;\n \tvar t2 *T2;\n@@ -3424,9 +3426,9 @@ than one source file, there may be more than one init() function, but\n only one per source file.\n \n Initialization code may contain "go" statements, but the functions\n-they invoke do not begin execution until initialization is complete.\n-Therefore, all initialization code is run in a single thread of\n-execution.\n+they invoke do not begin execution until initialization of the entire\n+program is complete. Therefore, all initialization code is run in a single\n+thread of execution.\n \n Furthermore, an "init()" function cannot be referred to from anywhere\n in a program. In particular, "init()" cannot be called explicitly, nor\n```
## コアとなるコードの解説
このコミットの最も重要な変更は、`Function Literals` のセクションにおける記述の変更です。
変更前は、以下のような「実装上の制限」が明記されていました。
Implementation restriction: A function literal can reference only its parameters, global variables, and variables declared within the function literal.
これは、関数リテラルが、その関数自身のパラメータ、グローバル変数、そして関数リテラル内で直接宣言された変数しか参照できないという、非常に厳しい制約を課していました。この制約があると、関数リテラルは「クロージャ」としての真の能力を発揮できません。なぜなら、クロージャの定義上、囲むスコープ(外側の関数など)の変数をキャプチャできることが不可欠だからです。
このコミットでは、上記の制限が完全に削除され、代わりに以下の記述が追加されました。
Function literals are "closures": they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible in any way.
この新しい記述は、Goの関数リテラルが正式に「クロージャ」として機能することを明確に宣言しています。
* **`Function literals are "closures"`**: 関数リテラルがクロージャであるという定義。
* **`they may refer to variables defined in a surrounding function`**: 囲む関数で定義された変数を参照できることを明示。これにより、外側のスコープの変数をキャプチャする能力が保証されます。
* **`Those variables are then shared between the surrounding function and the function literal`**: キャプチャされた変数が、囲む関数と関数リテラルの間で共有されることを示します。これは、値のコピーではなく、変数そのものへの参照がキャプチャされることを意味します。
* **`and they survive as long as they are accessible in any way`**: キャプチャされた変数のライフサイクルが、クロージャがアクセス可能な限り延長されることを保証します。これにより、囲む関数が実行を終えても、クロージャがその変数を参照し続ける限り、変数はガベージコレクションされません。
この変更により、Go言語は、より高度な関数型プログラミングのパターンや、状態を保持する柔軟なコード構造をサポートする基盤を確立しました。
## 関連リンク
* Go言語の公式ウェブサイト: [https://go.dev/](https://go.dev/)
* Go言語の仕様書: [https://go.dev/ref/spec](https://go.dev/ref/spec)
* Go言語の歴史に関するブログ記事など(Go 1.0以前の議論を含むもの)
## 参考にした情報源リンク
* Go言語のクロージャに関するドキュメントやチュートリアル (例: [https://yourbasic.org/golang/closures-explained/](https://yourbasic.org/golang/closures-explained/))
* Go言語の歴史に関する記事 (例: [https://en.wikipedia.org/wiki/Go_(programming_language)](https://en.wikipedia.org/wiki/Go_(programming_language)))
* Go言語の初期開発に関する議論やメーリングリストのアーカイブ(公開されている場合)
* Go 1.0リリースノートやそれ以前の変更ログ(Go 1.0以前の仕様変更の背景を理解するため)```markdown
# [インデックス 1637] ファイルの概要
このコミットは、Goプログラミング言語の初期の仕様書である `doc/go_spec.txt` に対する変更を記録しています。主な目的は、関数リテラル(クロージャ)に関する記述の修正と明確化、および仕様書内の誤字修正やTODOリストの更新です。特に、関数リテラルがクロージャとして振る舞うことに関する実装上の制限を削除し、その挙動を明示的に定義した点が重要です。
## コミット
commit d8a764cc7eb4e1919c152a4a121bd0585d4428ac Author: Robert Griesemer gri@golang.org Date: Fri Feb 6 17:01:10 2009 -0800
- removed todo and restriction from spec (closures)
- fixed typos, added a reminder for a todo
R=r
DELTA=23 (6 added, 4 deleted, 13 changed)
OCL=24611
CL=24615
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/d8a764cc7eb4e1919c152a4a121bd0585d4428ac](https://github.com/golang/go/commit/d8a764cc7eb4e1919c152a4a121bd0585d4428ac)
## 元コミット内容
このコミットは、Go言語の仕様書 `doc/go_spec.txt` に対して以下の変更を行っています。
* **TODOリストの更新**:
* 新しいTODO項目として「`;` と空のステートメント、ラベル宣言に関する奇妙な点」を追加。
* 以前のTODO項目「関数型に `func` を再導入すること、関数リテラルをスライスのように振る舞わせること、関数値を取得する際に `&` を不要にすること」を完了済みとしてマーク。これはRuss Cox氏からの提案でした。
* **関数リテラル(クロージャ)の仕様変更**:
* 最も重要な変更点として、関数リテラルに関する「実装上の制限」を削除。この制限は、「関数リテラルは、そのパラメータ、グローバル変数、および関数リテラル内で宣言された変数のみを参照できる」というものでした。
* この制限の削除と同時に、関数リテラルが「クロージャ」であるという明確な定義を追加。「関数リテラルは、囲む関数で定義された変数を参照できる。これらの変数は、囲む関数と関数リテラルの間で共有され、アクセス可能な限り存続する」と記述されました。
* **用語の修正**:
* 「Composite Literals」を「Composite literals」に、「Function Literals」を「Function literals」に修正(大文字から小文字へ)。
* **誤字修正**:
* インターフェースに関する記述で「interface M」を「method M」に修正。
* **初期化コードの実行順序に関する明確化**:
* `go` ステートメントによって呼び出される関数が、プログラム全体の初期化が完了するまで実行を開始しないことを明確化。これにより、すべての初期化コードが単一のスレッドで実行されることが保証されます。
* **日付の更新**:
* 仕様書の日付を「February 5, 2009」から「February 6, 2009」に更新。
## 変更の背景
このコミットは、Go言語がまだ開発の初期段階にあった2009年2月に行われたものです。Go言語は2009年11月に一般公開されるため、この時期は言語の核となる設計と仕様が活発に議論され、固められていた時期にあたります。
特に、関数リテラル(クロージャ)に関する変更は、Go言語の設計思想における重要な決定を反映しています。初期の仕様では、関数リテラルが参照できる変数に「実装上の制限」が設けられていましたが、これはクロージャの本来の強力な機能(囲むスコープの変数をキャプチャし、そのライフサイクルを延長する能力)を制限するものでした。このコミットによってその制限が撤廃され、Goの関数リテラルが真のクロージャとして機能することが明確にされました。これは、Goが関数型プログラミングのパラダイムを取り入れ、より柔軟で表現力豊かなコード記述を可能にする上で不可欠なステップでした。
また、仕様書内の誤字修正やTODOリストの整理は、言語仕様の正確性と完成度を高めるための継続的な取り組みの一環です。初期化コードの実行順序に関する明確化も、並行処理を重視するGo言語において、プログラムの挙動を予測可能にするための重要な改善です。
## 前提知識の解説
このコミットの理解には、以下の概念が役立ちます。
* **Go言語 (Golang)**: Googleで開発された静的型付けのコンパイル型プログラミング言語。シンプルさ、効率性、並行処理のサポートを重視しています。2009年11月に一般公開されました。
* **関数リテラル (Function Literals)**: Go言語における匿名関数(名前を持たない関数)のこと。コード内で直接定義され、変数に代入したり、関数の引数として渡したり、戻り値として返したりすることができます。
* **クロージャ (Closures)**: 関数リテラルが持つ特性の一つで、関数が定義された環境(囲むスコープ)の変数を「記憶」し、その関数がそのスコープ外で実行された際にもそれらの変数にアクセスできる機能です。これにより、関数が特定の状態を保持できるようになります。クロージャは、状態のカプセル化、高階関数、遅延実行などのパターンを可能にします。
* **Go言語の仕様書 (Go Programming Language Specification)**: Go言語の構文、セマンティクス、標準ライブラリの動作などを定義する公式文書。言語の設計と実装の基盤となります。
* **`go` ステートメント**: Go言語におけるゴルーチン(軽量スレッド)を起動するためのキーワード。`go` の後に続く関数呼び出しを新しいゴルーチンで並行して実行します。
* **初期化 (Initialization)**: Goプログラムが実行される前に、パッケージレベルの変数や `init()` 関数が実行されるプロセス。このプロセスは、プログラムの起動時に必要なセットアップを行います。
## 技術的詳細
このコミットの技術的詳細の核心は、Go言語におけるクロージャのセマンティクスが初期段階でどのように確立されたかという点にあります。
1. **「実装上の制限」の撤廃**:
変更前の仕様では、関数リテラルが参照できる変数の範囲が厳しく制限されていました。これは、クロージャの実装が複雑であること、あるいは初期の設計段階でその挙動が完全に固まっていなかったことを示唆しています。この制限が撤廃されたことで、Goの関数リテラルは、他の多くの現代的な言語(JavaScript、Pythonなど)と同様に、定義されたスコープ内の非ローカル変数を自由にキャプチャできるようになりました。
2. **クロージャの明確な定義**:
制限の撤廃と同時に、「Function literals are "closures": they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible in any way.」という記述が追加されました。これは、Goの関数リテラルが正式に「クロージャ」として機能することを明確にしています。
* **`Function literals are "closures"`**: 関数リテラルがクロージャであるという定義。
* **`they may refer to variables defined in a surrounding function`**: 囲む関数で定義された変数を参照できることを明示。これにより、外側のスコープの変数をキャプチャする能力が保証されます。
* **`Those variables are then shared between the surrounding function and the function literal`**: キャプチャされた変数が、囲む関数と関数リテラルの間で共有されることを示します。これは、値のコピーではなく、変数そのものへの参照がキャプチャされることを意味します。
* **`and they survive as long as they are accessible in any way`**: キャプチャされた変数のライフサイクルが、クロージャがアクセス可能な限り延長されることを保証します。これにより、囲む関数が実行を終えても、クロージャがその変数を参照し続ける限り、変数はガベージコレクションされません。
3. **初期化コードの実行順序**:
`go` ステートメントで起動されるゴルーチンが「プログラム全体の初期化が完了するまで実行を開始しない」という明確化は、Goの並行処理モデルにおける重要な保証です。これにより、初期化フェーズ中に競合状態が発生するのを防ぎ、プログラムが予測可能な状態で起動することを保証します。すべての `init()` 関数とパッケージレベルの変数の初期化が完了してから初めて、`go` ステートメントによって起動されたゴルーチンが実行を開始します。これは、Goの設計哲学である「シンプルさと安全性」を反映したものです。
4. **用語の統一**:
「Composite Literals」や「Function Literals」の「Literals」を小文字に統一した変更は、Go言語の仕様書全体での用語の一貫性を保つための細かながら重要な改善です。これは、公式文書の品質と読みやすさに貢献します。
これらの変更は、Go言語がその後の成功を収める上で不可欠な、堅牢で一貫性のある言語セマンティクスを確立する上で重要な役割を果たしました。
## コアとなるコードの変更箇所
変更はすべて `doc/go_spec.txt` ファイル内で行われています。
```diff
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -3,7 +3,7 @@ The Go Programming Language Specification (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson
-(February 5, 2009)
+(February 6, 2009)
----
@@ -37,6 +37,7 @@ Decisions in need of integration into the doc:
Todo's:
+[ ] there is some funny-ness regarding ';' and empty statements and label decls
[ ] document illegality of package-external tuple assignments to structs
w/ private fields: P.T{1, 2} illegal since same as P.T{a: 1, b: 2} for
a T struct { a b int }.\
@@ -68,13 +69,13 @@ Smaller issues:
ta for loop that is following, and can break L be used inside it?
[ ] Russ: If we use x.(T) for all conversions, we could use T() for "construction"
and type literals - would resolve the parsing ambiguity of T{} in if's
-[ ] Russ: consider re-introducing "func" for function type. Make function literals
- behave like slices, etc. Require no &'s to get a function value (solves issue
- of func{} vs &func{} vs &func_name).
-
+-[ ] Russ: consider re-introducing "func" for function type. Make function literals
+- behave like slices, etc. Require no &'s to get a function value (solves issue
+- of func{} vs &func{} vs &func_name).
+
Closed:
+[x] Russ: consider re-introducing "func" for function type. Make function literals
+\tbehave like slices, etc. Require no &'s to get a function value (solves issue
+\tof func{} vs &func{} vs &func_name).
[x] onreturn/undo statement - now: defer statement
[x] comparison of non-basic types: what do we allow? what do we allow in interfaces
what about maps (require ==, copy and hash)
@@ -203,8 +204,8 @@ Contents
Operands
Constants
Qualified identifiers
-- Composite Literals
-- Function Literals
++ Composite literals
++ Function literals
Primary expressions
Selectors
@@ -1794,7 +1795,7 @@ TODO(gri) expand this section.
PackageName = identifier .
-Composite Literals
+Composite literals
----
Literals for composite data structures consist of the type of the value
@@ -1852,7 +1853,7 @@ TODO: Consider adding helper syntax for nested composites
(avoids repeating types but complicates the spec needlessly.)
-Function Literals
+Function literals
----
A function literal represents an anonymous function. It consists of a
@@ -1872,9 +1873,10 @@ corresponding function type, or invoked directly.
f := func(x, y int) int { return x + y; }
func(ch chan int) { ch <- ACK; } (reply_chan)
-Implementation restriction: A function literal can reference only
-its parameters, global variables, and variables declared within the
-function literal.
+Function literals are "closures": they may refer to variables
+defined in a surrounding function. Those variables are then shared between
+the surrounding function and the function literal, and they survive as long
+as they are accessible in any way.
Primary expressions
@@ -2418,7 +2420,7 @@ denotes a method: Effect is as described above, converts into function.\n \n If T is an interface type, the expression t.M does not determine which\n underlying type's M is called until the point of the call itself. Thus given\n-T1 and T2, both implementing interface I with interface M, the sequence\n+T1 and T2, both implementing interface I with method M, the sequence\n \n \tvar t1 *T1;\n \tvar t2 *T2;\n@@ -3424,9 +3426,9 @@ than one source file, there may be more than one init() function, but\n only one per source file.\n \n Initialization code may contain "go" statements, but the functions\n-they invoke do not begin execution until initialization is complete.\n-Therefore, all initialization code is run in a single thread of\n-execution.\n+they invoke do not begin execution until initialization of the entire\n+program is complete. Therefore, all initialization code is run in a single\n+thread of execution.\n \n Furthermore, an "init()" function cannot be referred to from anywhere\n in a program. In particular, "init()" cannot be called explicitly, nor\n```
## コアとなるコードの解説
このコミットの最も重要な変更は、`Function Literals` のセクションにおける記述の変更です。
変更前は、以下のような「実装上の制限」が明記されていました。
Implementation restriction: A function literal can reference only its parameters, global variables, and variables declared within the function literal.
これは、関数リテラルが、その関数自身のパラメータ、グローバル変数、そして関数リテラル内で直接宣言された変数しか参照できないという、非常に厳しい制約を課していました。この制約があると、関数リテラルは「クロージャ」としての真の能力を発揮できません。なぜなら、クロージャの定義上、囲むスコープ(外側の関数など)の変数をキャプチャできることが不可欠だからです。
このコミットでは、上記の制限が完全に削除され、代わりに以下の記述が追加されました。
Function literals are "closures": they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible in any way.
この新しい記述は、Goの関数リテラルが正式に「クロージャ」として機能することを明確に宣言しています。
* **`Function literals are "closures"`**: 関数リテラルがクロージャであるという定義。
* **`they may refer to variables defined in a surrounding function`**: 囲む関数で定義された変数を参照できることを明示。これにより、外側のスコープの変数をキャプチャする能力が保証されます。
* **`Those variables are then shared between the surrounding function and the function literal`**: キャプチャされた変数が、囲む関数と関数リテラルの間で共有されることを示します。これは、値のコピーではなく、変数そのものへの参照がキャプチャされることを意味します。
* **`and they survive as long as they are accessible in any way`**: キャプチャされた変数のライフサイクルが、クロージャがアクセス可能な限り延長されることを保証します。これにより、囲む関数が実行を終えても、クロージャがその変数を参照し続ける限り、変数はガベージコレクションされません。
この変更により、Go言語は、より高度な関数型プログラミングのパターンや、状態を保持する柔軟なコード構造をサポートする基盤を確立しました。
## 関連リンク
* Go言語の公式ウェブサイト: [https://go.dev/](https://go.dev/)
* Go言語の仕様書: [https://go.dev/ref/spec](https://go.dev/ref/spec)
* Go言語の歴史に関するブログ記事など(Go 1.0以前の議論を含むもの)
## 参考にした情報源リンク
* Go言語のクロージャに関するドキュメントやチュートリアル (例: [https://yourbasic.org/golang/closures-explained/](https://yourbasic.org/golang/closures-explained/))
* Go言語の歴史に関する記事 (例: [https://en.wikipedia.org/wiki/Go_(programming_language)](https://en.wikipedia.org/wiki/Go_(programming_language)))
* Go言語の初期開発に関する議論やメーリングリストのアーカイブ(公開されている場合)
* Go 1.0リリースノートやそれ以前の変更ログ(Go 1.0以前の仕様変更の背景を理解するため)