[インデックス 14179] ファイルの概要
このコミットは、Go言語の仕様書 doc/go_spec.html
に対する変更であり、make()
関数の引数に関する制限をより明確に定義し、特に定数引数に対するコンパイル時エラーの挙動を統一することを目的としています。これにより、make()
の挙動がインデックス式(配列やスライスへのアクセス)の挙動と一貫性を持つようになります。
コミット
commit 3bde00033b8d1ff7c494d10b1343178c32abb7ad
Author: Robert Griesemer <gri@golang.org>
Date: Fri Oct 19 10:11:06 2012 -0700
go spec: define make() restrictions as for index expressions
This is a language change: Until now, the spec required run-
time panics for some of these errors. Note that gc and gccgo
implemented this inconsistently, and that both compilers already
reported compile-time errors in some cases. This change makes
make() behave along the same vein as index expressions.
This addresses the spec aspect of issue 4085.
R=r, rsc, iant, ken
CC=golang-dev
https://golang.org/cl/6725053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3bde00033b8d1ff7c494d10b1343178c32abb7ad
元コミット内容
Go言語の仕様書において、make()
関数の制限をインデックス式と同様に定義する。
これは言語仕様の変更である。これまで、仕様ではこれらのエラーの一部に対して実行時パニックを要求していた。gc
と gccgo
の両コンパイラがこれを一貫性なく実装しており、また両コンパイラはすでに一部のケースでコンパイル時エラーを報告していたことに注意。この変更により、make()
はインデックス式と同じ挙動をするようになる。
これは issue 4085 の仕様に関する側面に対応するものである。
変更の背景
この変更の背景には、Go言語の make()
関数におけるエラー処理の一貫性の欠如と、コンパイラの実装間の差異がありました。
-
仕様と実装の不一致: 従来のGo言語の仕様では、
make()
関数の引数(特にスライスやチャネルの容量指定)が不正な場合(例: 負の値、len
がcap
より大きい場合など)には「実行時パニック (run-time panic)」が発生するとされていました。しかし、実際のコンパイラ(gc
とgccgo
)は、一部の明らかな不正な定数引数に対しては、すでにコンパイル時にエラーを報告していました。この不一致は、開発者にとって混乱の原因となり、予測可能な挙動を妨げていました。 -
一貫性の追求: Go言語の設計哲学の一つに「シンプルさと一貫性」があります。インデックス式(例:
a[i]
)では、インデックスi
が配列やスライスの範囲外である場合、実行時パニックが発生します。しかし、コンパイル時にインデックスが定数で、かつ明らかに範囲外であることが判明している場合は、コンパイル時エラーとして扱われます。このコミットは、make()
関数の引数に対しても同様のロジックを適用し、定数引数における不正な値はコンパイル時エラーとして扱うことで、言語全体の一貫性を高めることを目指しました。 -
Issue 4085への対応: この変更は、Go言語のIssueトラッカーで報告された「Issue 4085: spec: make() should have compile-time checks for constant arguments」に対応するものです。このIssueは、
make()
の定数引数に対するコンパイル時チェックの必要性を提起しており、このコミットはその仕様側の側面を解決するものです。
これらの背景から、Go言語の仕様をより厳密にし、コンパイラの挙動と整合させ、開発者にとってより予測可能で堅牢なコード作成を支援するために、この変更が導入されました。
前提知識の解説
このコミットを理解するためには、以下のGo言語の基本的な概念と、コンパイラの挙動に関する知識が必要です。
-
make()
関数:- Go言語の組み込み関数の一つで、スライス、マップ、チャネルといった組み込み型を初期化し、メモリを割り当てるために使用されます。
- スライス:
make([]T, len, cap)
の形式で、要素の型T
、初期の長さlen
、容量cap
を指定します。cap
は省略可能で、その場合はlen
と同じ値になります。len
はcap
を超えることはできません。 - マップ:
make(map[K]V, initialCapacity)
の形式で、キーの型K
、値の型V
、および初期容量initialCapacity
を指定します。 - チャネル:
make(chan T, bufferCapacity)
の形式で、チャネルの要素の型T
、およびバッファ容量bufferCapacity
を指定します。バッファ容量が0の場合は非バッファチャネル、正の場合はバッファチャネルになります。 make()
の引数len
,cap
,initialCapacity
,bufferCapacity
は整数型である必要があります。
-
実行時パニック (Run-time Panic):
- Goプログラムの実行中に発生する回復不可能なエラーです。例えば、nilポインタのデリファレンス、配列の範囲外アクセス、ゼロ除算などが挙げられます。パニックが発生すると、通常のプログラムフローは中断され、スタックトレースが出力されてプログラムが終了します(
recover
関数で捕捉されない限り)。 - 従来の仕様では、
make()
の引数が不正な場合に実行時パニックが発生するとされていました。
- Goプログラムの実行中に発生する回復不可能なエラーです。例えば、nilポインタのデリファレンス、配列の範囲外アクセス、ゼロ除算などが挙げられます。パニックが発生すると、通常のプログラムフローは中断され、スタックトレースが出力されてプログラムが終了します(
-
コンパイル時エラー (Compile-time Error):
- プログラムがコンパイルされる段階で検出されるエラーです。文法エラー、型不一致、未定義の変数参照など、Go言語の構文規則や型システムに違反している場合に発生します。コンパイル時エラーが発生すると、実行可能ファイルは生成されず、プログラムは実行できません。
- コンパイル時エラーは、実行時パニックよりも早期に問題を検出できるため、より堅牢なソフトウェア開発に寄与します。
-
定数 (Constants):
- Go言語における定数は、コンパイル時に値が決定される不変のエンティティです。数値、ブール値、文字列の定数があります。
- 定数式は、コンパイル時に評価され、その結果も定数となります。
-
インデックス式 (Index Expressions):
- 配列、スライス、文字列、マップの要素にアクセスするために使用される式です。例:
a[i]
。 - インデックス
i
が定数であり、かつコンパイル時に範囲外であることが明らかな場合、コンパイル時エラーとなります。例えば、var a [5]int; a[10]
はコンパイル時エラーです。 - インデックス
i
が変数であり、実行時に範囲外になった場合、実行時パニックとなります。
- 配列、スライス、文字列、マップの要素にアクセスするために使用される式です。例:
-
Goコンパイラ (
gc
とgccgo
):gc
: Go言語の公式コンパイラであり、Goツールチェーンの一部です。gccgo
: GCC (GNU Compiler Collection) のGo言語フロントエンドです。- これらのコンパイラは、Go言語のソースコードを機械語に変換しますが、実装の詳細やエラーチェックの厳密さにおいて、過去には一部で異なる挙動を示すことがありました。
このコミットは、make()
の引数が定数である場合に、インデックス式と同様にコンパイル時に不正な値を検出してエラーとすることで、Go言語の堅牢性と開発体験を向上させることを目指しています。
技術的詳細
このコミットの技術的詳細な変更点は、Go言語の仕様書 doc/go_spec.html
の make()
関数に関する記述を修正し、特に引数が定数である場合の挙動を明確化した点にあります。
変更前は、make()
の引数 n
および m
(スライスやチャネルのサイズ引数)が不正な場合(例: n
が負の値、n
が m
より大きい場合、または n
や m
が int
で表現できない場合)には「実行時パニック」が発生すると規定されていました。
変更後の仕様では、以下の点が明確化されました。
- サイズ引数の型:
n
とm
は引き続き整数値である必要があります。 - 定数引数に対するコンパイル時チェックの導入:
- 「定数サイズ引数は負であってはならない (A constant size argument must not be negative)」と明記されました。これは、
make([]int, -1)
のようなコードがコンパイル時にエラーとなることを意味します。 - 「もし
n
とm
の両方が提供され、かつ定数である場合、n
はm
より大きくあってはならない (and if bothn
andm
are provided and are constant, thenn
must be no larger thanm
)」と明記されました。これは、make([]int, 10, 0)
のようなコード(len
がcap
より大きい)がコンパイル時にエラーとなることを意味します。
- 「定数サイズ引数は負であってはならない (A constant size argument must not be negative)」と明記されました。これは、
- 実行時パニックの維持:
- 上記のような定数引数に対するコンパイル時チェックが導入された一方で、「もし
n
が負であるか、実行時にm
より大きい場合、実行時パニックが発生する (Ifn
is negative or larger thanm
at run time, a run-time panic occurs)」という規定は維持されました。これは、引数が変数であり、その変数の値が実行時に不正になった場合に、引き続きパニックが発生することを示しています。
- 上記のような定数引数に対するコンパイル時チェックが導入された一方で、「もし
この変更により、make()
の引数が定数である場合には、コンパイラがより厳密なチェックを行い、不正なコードを早期に(コンパイル時に)検出できるようになります。これにより、開発者は実行時エラーに遭遇する前に問題を修正でき、デバッグの労力を削減できます。
また、この変更は、Go言語のコンパイラ gc
と gccgo
がこれまで一貫性なく実装していた挙動を、仕様レベルで統一する役割も果たします。一部のケースではすでにコンパイル時エラーを報告していたコンパイラの挙動が、正式な仕様として認められ、すべてのコンパイラがそれに従うべき基準が確立されました。
この修正は、make()
の挙動をインデックス式(例: a[i]
)の挙動と「同じ流れ (along the same vein)」にするという設計思想に基づいています。インデックス式でも、定数インデックスが範囲外であればコンパイル時エラー、変数インデックスが実行時に範囲外であれば実行時パニックとなります。この一貫性により、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 October 17, 2012",
+ "Subtitle": "Version of October 19, 2012",
"Path": "/ref/spec"
}-->
@@ -4920,15 +4920,18 @@ make(T, n) channel asynchronous channel of type T, buffer size n
<p>
-The arguments <code>n</code> and <code>m</code> must be of integer type.
-A <a href="#Run_time_panics">run-time panic</a> occurs if <code>n</code>
-is negative or larger than <code>m</code>, or if <code>n</code> or
-<code>m</code> cannot be represented by an <code>int</code>.
+The size arguments <code>n</code> and <code>m</code> must be integer values.
+A <a href="#Constants">constant</a> size argument must not be negative, and
+if both <code>n</code> and <code>m</code> are provided and are constant, then
+<code>n</code> must be no larger than <code>m</code>.
+If <code>n</code> is negative or larger than <code>m</code> at run time,
+a <a href="#Run_time_panics">run-time panic</a> occurs.
</p>
<pre>
s := make([]int, 10, 100) // slice with len(s) == 10, cap(s) == 100
-s := make([]int, 10) // slice with len(s) == cap(s) == 10
+s := make([]int, 1e3) // slice with len(s) == cap(s) == 1000
+s := make([]int, 10, 0) // illegal: len(s) > cap(s)
c := make(chan int, 10) // channel with a buffer size of 10
m := make(map[string]int, 100) // map with initial space for 100 elements
</pre>
主な変更点は以下の通りです。
-
仕様書のバージョン日付の更新:
Subtitle
が "Version of October 17, 2012" から "Version of October 19, 2012" に変更されています。これは、仕様の更新日を示します。
-
make()
関数の引数に関する記述の修正:- 変更前:
The arguments <code>n</code> and <code>m</code> must be of integer type. A <a href="#Run_time_panics">run-time panic</a> occurs if <code>n</code> is negative or larger than <code>m</code>, or if <code>n</code> or <code>m</code> cannot be represented by an <code>int</code>.
- 変更後:
この部分が、定数引数に対するコンパイル時チェックの導入と、実行時パニックの条件を明確にする主要な変更です。The size arguments <code>n</code> and <code>m</code> must be integer values. A <a href="#Constants">constant</a> size argument must not be negative, and if both <code>n</code> and <code>m</code> are provided and are constant, then <code>n</code> must be no larger than <code>m</code>. If <code>n</code> is negative or larger than <code>m</code> at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
- 変更前:
-
make()
の使用例の修正:- 変更前:
s := make([]int, 10) // slice with len(s) == cap(s) == 10
- 変更後:
s := make([]int, 1e3) // slice with len(s) == cap(s) == 1000 s := make([]int, 10, 0) // illegal: len(s) > cap(s)
make([]int, 10)
の例がmake([]int, 1e3)
に変更され、さらにs := make([]int, 10, 0)
という「不正な」例が追加されています。この不正な例は、len
(10) がcap
(0) より大きい場合にコンパイル時エラーとなることを示すものです。
- 変更前:
これらの変更は、Go言語の仕様書における make()
関数のセマンティクスをより厳密かつ明確にし、特に定数引数に対するコンパイラの挙動を統一することを目的としています。
コアとなるコードの解説
このコミットのコアとなるコードの変更は、Go言語の仕様書 doc/go_spec.html
内の make()
関数の説明部分にあります。具体的には、make()
のサイズ引数 n
と m
に関する制約の記述が修正されました。
変更前の記述は、n
と m
が整数型であること、そして n
が負であるか m
より大きい場合、または n
や m
が int
で表現できない場合に実行時パニックが発生するというものでした。
変更後の記述は、以下の重要な点を導入しています。
-
定数引数に対するコンパイル時チェックの明示:
A <a href="#Constants">constant</a> size argument must not be negative, and if both <code>n</code> and <code>m</code> are provided and are constant, then <code>n</code> must be no larger than <code>m</code>.
- この文は、
make()
の引数として定数が使用される場合に、コンパイラが負の値やlen > cap
のような不正な状態をコンパイル時に検出してエラーとすることを明確にしています。これにより、開発者は実行時パニックに遭遇する前に、コードの論理的な誤りを修正できます。これは、Go言語の堅牢性を高める上で非常に重要です。
-
実行時パニックの条件の再定義:
If <code>n</code> is negative or larger than <code>m</code> at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
- この文は、引数が変数である場合など、コンパイル時には不正な値が確定できないケースにおいて、実行時に
n
が負であるかm
より大きい場合に引き続きパニックが発生することを明確にしています。これにより、コンパイル時チェックが適用されない動的なシナリオでの安全性が保証されます。
-
具体例の追加:
s := make([]int, 10, 0) // illegal: len(s) > cap(s)
- この新しい例は、
len
がcap
より大きいという不正なmake()
の呼び出しが、コンパイル時に「illegal」(不正)として扱われることを示しています。これは、上記の仕様変更を具体的に示すものです。
この変更は、Go言語のコンパイラがすでに一部の定数引数に対してコンパイル時エラーを報告していたという事実を仕様に反映させ、言語全体の一貫性を向上させるものです。これにより、make()
の挙動が、インデックス式における定数と変数の扱いと同様になり、Go言語の設計原則である「予測可能性」と「シンプルさ」がさらに強化されます。開発者は、より早期にエラーを検出し、より信頼性の高いGoプログラムを記述できるようになります。
関連リンク
- Go言語の仕様書: https://go.dev/ref/spec
- Go言語のIssue 4085: https://github.com/golang/go/issues/4085
- このコミットのGo Gerritレビュー: https://golang.org/cl/6725053
参考にした情報源リンク
- Go言語の公式ドキュメント
- GitHubのGoリポジトリのコミット履歴
- Go言語のIssueトラッカー
- Go言語のメーリングリストアーカイブ (golang-dev)
- Go言語の
make
関数に関する一般的な解説記事 - Go言語の定数に関する解説記事
- Go言語のパニックと回復に関する解説記事
[インデックス 14179] ファイルの概要
このコミットは、Go言語の仕様書 doc/go_spec.html
に対する変更であり、make()
関数の引数に関する制限をより明確に定義し、特に定数引数に対するコンパイル時エラーの挙動を統一することを目的としています。これにより、make()
の挙動がインデックス式(配列やスライスへのアクセス)の挙動と一貫性を持つようになります。
コミット
commit 3bde00033b8d1ff7c494d10b1343178c32abb7ad
Author: Robert Griesemer <gri@golang.org>
Date: Fri Oct 19 10:11:06 2012 -0700
go spec: define make() restrictions as for index expressions
This is a language change: Until now, the spec required run-
time panics for some of these errors. Note that gc and gccgo
implemented this inconsistently, and that both compilers already
reported compile-time errors in some cases. This change makes
make() behave along the same vein as index expressions.
This addresses the spec aspect of issue 4085.
R=r, rsc, iant, ken
CC=golang-dev
https://golang.org/cl/6725053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3bde00033b8d1ff7c494d10b1343178c32abb7ad
元コミット内容
Go言語の仕様書において、make()
関数の制限をインデックス式と同様に定義する。
これは言語仕様の変更である。これまで、仕様ではこれらのエラーの一部に対して実行時パニックを要求していた。gc
と gccgo
の両コンパイラがこれを一貫性なく実装しており、また両コンパイラはすでに一部のケースでコンパイル時エラーを報告していたことに注意。この変更により、make()
はインデックス式と同じ挙動をするようになる。
これは issue 4085 の仕様に関する側面に対応するものである。
変更の背景
この変更の背景には、Go言語の make()
関数におけるエラー処理の一貫性の欠如と、コンパイラの実装間の差異がありました。
-
仕様と実装の不一致: 従来のGo言語の仕様では、
make()
関数の引数(特にスライスやチャネルの容量指定)が不正な場合(例: 負の値、len
がcap
より大きい場合など)には「実行時パニック (run-time panic)」が発生するとされていました。しかし、実際のコンパイラ(gc
とgccgo
)は、一部の明らかな不正な定数引数に対しては、すでにコンパイル時にエラーを報告していました。この不一致は、開発者にとって混乱の原因となり、予測可能な挙動を妨げていました。 -
一貫性の追求: Go言語の設計哲学の一つに「シンプルさと一貫性」があります。インデックス式(例:
a[i]
)では、インデックスi
が配列やスライスの範囲外である場合、実行時パニックが発生します。しかし、コンパイル時にインデックスが定数で、かつ明らかに範囲外であることが判明している場合は、コンパイル時エラーとして扱われます。このコミットは、make()
関数の引数に対しても同様のロジックを適用し、定数引数における不正な値はコンパイル時エラーとして扱うことで、言語全体の一貫性を高めることを目指しました。 -
Issue 4085への対応: この変更は、Go言語のIssueトラッカーで報告された「Issue 4085: spec: make() should have compile-time checks for constant arguments」に対応するものです。このIssueは、
make()
の定数引数に対するコンパイル時チェックの必要性を提起しており、このコミットはその仕様側の側面を解決するものです。
これらの背景から、Go言語の仕様をより厳密にし、コンパイラの挙動と整合させ、開発者にとってより予測可能で堅牢なコード作成を支援するために、この変更が導入されました。
前提知識の解説
このコミットを理解するためには、以下のGo言語の基本的な概念と、コンパイラの挙動に関する知識が必要です。
-
make()
関数:- Go言語の組み込み関数の一つで、スライス、マップ、チャネルといった組み込み型を初期化し、メモリを割り当てるために使用されます。
- スライス:
make([]T, len, cap)
の形式で、要素の型T
、初期の長さlen
、容量cap
を指定します。cap
は省略可能で、その場合はlen
と同じ値になります。len
はcap
を超えることはできません。 - マップ:
make(map[K]V, initialCapacity)
の形式で、キーの型K
、値の型V
、および初期容量initialCapacity
を指定します。 - チャネル:
make(chan T, bufferCapacity)
の形式で、チャネルの要素の型T
、およびバッファ容量bufferCapacity
を指定します。バッファ容量が0の場合は非バッファチャネル、正の場合はバッファチャネルになります。 make()
の引数len
,cap
,initialCapacity
,bufferCapacity
は整数型である必要があります。
-
実行時パニック (Run-time Panic):
- Goプログラムの実行中に発生する回復不可能なエラーです。例えば、nilポインタのデリファレンス、配列の範囲外アクセス、ゼロ除算などが挙げられます。パニックが発生すると、通常のプログラムフローは中断され、スタックトレースが出力されてプログラムが終了します(
recover
関数で捕捉されない限り)。 - 従来の仕様では、
make()
の引数が不正な場合に実行時パニックが発生するとされていました。
- Goプログラムの実行中に発生する回復不可能なエラーです。例えば、nilポインタのデリファレンス、配列の範囲外アクセス、ゼロ除算などが挙げられます。パニックが発生すると、通常のプログラムフローは中断され、スタックトレースが出力されてプログラムが終了します(
-
コンパイル時エラー (Compile-time Error):
- プログラムがコンパイルされる段階で検出されるエラーです。文法エラー、型不一致、未定義の変数参照など、Go言語の構文規則や型システムに違反している場合に発生します。コンパイル時エラーが発生すると、実行可能ファイルは生成されず、プログラムは実行できません。
- コンパイル時エラーは、実行時パニックよりも早期に問題を検出できるため、より堅牢なソフトウェア開発に寄与します。
-
定数 (Constants):
- Go言語における定数は、コンパイル時に値が決定される不変のエンティティです。数値、ブール値、文字列の定数があります。
- 定数式は、コンパイル時に評価され、その結果も定数となります。
-
インデックス式 (Index Expressions):
- 配列、スライス、文字列、マップの要素にアクセスするために使用される式です。例:
a[i]
。 - インデックス
i
が定数であり、かつコンパイル時に範囲外であることが明らかな場合、コンパイル時エラーとなります。例えば、var a [5]int; a[10]
はコンパイル時エラーです。 - インデックス
i
が変数であり、実行時に範囲外になった場合、実行時パニックとなります。
- 配列、スライス、文字列、マップの要素にアクセスするために使用される式です。例:
-
Goコンパイラ (
gc
とgccgo
):gc
: Go言語の公式コンパイラであり、Goツールチェーンの一部です。gccgo
: GCC (GNU Compiler Collection) のGo言語フロントエンドです。- これらのコンパイラは、Go言語のソースコードを機械語に変換しますが、実装の詳細やエラーチェックの厳密さにおいて、過去には一部で異なる挙動を示すことがありました。
このコミットは、make()
の引数が定数である場合に、インデックス式と同様にコンパイル時に不正な値を検出してエラーとすることで、Go言語の堅牢性と開発体験を向上させることを目指しています。
技術的詳細
このコミットの技術的詳細な変更点は、Go言語の仕様書 doc/go_spec.html
の make()
関数に関する記述を修正し、特に引数が定数である場合の挙動を明確化した点にあります。
変更前は、make()
の引数 n
および m
(スライスやチャネルのサイズ引数)が不正な場合(例: 負の値、n
が m
より大きい場合、または n
や m
が int
で表現できない場合)には「実行時パニック」が発生するとされていました。
変更後の仕様では、以下の点が明確化されました。
- サイズ引数の型:
n
とm
は引き続き整数値である必要があります。 - 定数引数に対するコンパイル時チェックの導入:
- 「定数サイズ引数は負であってはならない (A constant size argument must not be negative)」と明記されました。これは、
make([]int, -1)
のようなコードがコンパイル時にエラーとなることを意味します。 - 「もし
n
とm
の両方が提供され、かつ定数である場合、n
はm
より大きくあってはならない (and if bothn
andm
are provided and are constant, thenn
must be no larger thanm
)」と明記されました。これは、make([]int, 10, 0)
のようなコード(len
がcap
より大きい)がコンパイル時にエラーとなることを意味します。
- 「定数サイズ引数は負であってはならない (A constant size argument must not be negative)」と明記されました。これは、
- 実行時パニックの維持:
- 上記のような定数引数に対するコンパイル時チェックが導入された一方で、「もし
n
が負であるか、実行時にm
より大きい場合、実行時パニックが発生する (Ifn
is negative or larger thanm
at run time, a run-time panic occurs)」という規定は維持されました。これは、引数が変数であり、その変数の値が実行時に不正になった場合に、引き続きパニックが発生することを示しています。
- 上記のような定数引数に対するコンパイル時チェックが導入された一方で、「もし
この変更により、make()
の引数が定数である場合には、コンパイラがより厳密なチェックを行い、不正なコードを早期に(コンパイル時に)検出できるようになります。これにより、開発者は実行時エラーに遭遇する前に問題を修正でき、デバッグの労力を削減できます。
また、この変更は、Go言語のコンパイラ gc
と gccgo
がこれまで一貫性なく実装していた挙動を、仕様レベルで統一する役割も果たします。一部のケースではすでにコンパイル時エラーを報告していたコンパイラの挙動が、正式な仕様として認められ、すべてのコンパイラがそれに従うべき基準が確立されました。
この修正は、make()
の挙動をインデックス式(例: a[i]
)の挙動と「同じ流れ (along the same vein)」にするという設計思想に基づいています。インデックス式でも、定数インデックスが範囲外であればコンパイル時エラー、変数インデックスが実行時に範囲外であれば実行時パニックとなります。この一貫性により、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 October 17, 2012",
+ "Subtitle": "Version of October 19, 2012",
"Path": "/ref/spec"
}-->
@@ -4920,15 +4920,18 @@ make(T, n) channel asynchronous channel of type T, buffer size n
<p>
-The arguments <code>n</code> and <code>m</code> must be of integer type.
-A <a href="#Run_time_panics">run-time panic</a> occurs if <code>n</code>
-is negative or larger than <code>m</code>, or if <code>n</code> or
-<code>m</code> cannot be represented by an <code>int</code>.
+The size arguments <code>n</code> and <code>m</code> must be integer values.
+A <a href="#Constants">constant</a> size argument must not be negative, and
+if both <code>n</code> and <code>m</code> are provided and are constant, then
+<code>n</code> must be no larger than <code>m</code>.
+If <code>n</code> is negative or larger than <code>m</code> at run time,
+a <a href="#Run_time_panics">run-time panic</a> occurs.
</p>
<pre>
s := make([]int, 10, 100) // slice with len(s) == 10, cap(s) == 100
-s := make([]int, 10) // slice with len(s) == cap(s) == 10
+s := make([]int, 1e3) // slice with len(s) == cap(s) == 1000
+s := make([]int, 10, 0) // illegal: len(s) > cap(s)
c := make(chan int, 10) // channel with a buffer size of 10
m := make(map[string]int, 100) // map with initial space for 100 elements
</pre>
主な変更点は以下の通りです。
-
仕様書のバージョン日付の更新:
Subtitle
が "Version of October 17, 2012" から "Version of October 19, 2012" に変更されています。これは、仕様の更新日を示します。
-
make()
関数の引数に関する記述の修正:- 変更前:
The arguments <code>n</code> and <code>m</code> must be of integer type. A <a href="#Run_time_panics">run-time panic</a> occurs if <code>n</code> is negative or larger than <code>m</code>, or if <code>n</code> or <code>m</code> cannot be represented by an <code>int</code>.
- 変更後:
この部分が、定数引数に対するコンパイル時チェックの導入と、実行時パニックの条件を明確にする主要な変更です。The size arguments <code>n</code> and <code>m</code> must be integer values. A <a href="#Constants">constant</a> size argument must not be negative, and if both <code>n</code> and <code>m</code> are provided and are constant, then <code>n</code> must be no larger than <code>m</code>. If <code>n</code> is negative or larger than <code>m</code> at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
- 変更前:
-
make()
の使用例の修正:- 変更前:
s := make([]int, 10) // slice with len(s) == cap(s) == 10
- 変更後:
s := make([]int, 1e3) // slice with len(s) == cap(s) == 1000 s := make([]int, 10, 0) // illegal: len(s) > cap(s)
make([]int, 10)
の例がmake([]int, 1e3)
に変更され、さらにs := make([]int, 10, 0)
という「不正な」例が追加されています。この不正な例は、len
(10) がcap
(0) より大きい場合にコンパイル時エラーとなることを示すものです。
- 変更前:
これらの変更は、Go言語の仕様書における make()
関数のセマンティクスをより厳密かつ明確にし、特に定数引数に対するコンパイラの挙動を統一することを目的としています。
コアとなるコードの解説
このコミットのコアとなるコードの変更は、Go言語の仕様書 doc/go_spec.html
内の make()
関数の説明部分にあります。具体的には、make()
のサイズ引数 n
と m
に関する制約の記述が修正されました。
変更前の記述は、n
と m
が整数型であること、そして n
が負であるか m
より大きい場合、または n
や m
が int
で表現できない場合に実行時パニックが発生するというものでした。
変更後の記述は、以下の重要な点を導入しています。
-
定数引数に対するコンパイル時チェックの明示:
A <a href="#Constants">constant</a> size argument must not be negative, and if both <code>n</code> and <code>m</code> are provided and are constant, then <code>n</code> must be no larger than <code>m</code>.
- この文は、
make()
の引数として定数が使用される場合に、コンパイラが負の値やlen > cap
のような不正な状態をコンパイル時に検出してエラーとすることを明確にしています。これにより、開発者は実行時パニックに遭遇する前に、コードの論理的な誤りを修正できます。これは、Go言語の堅牢性を高める上で非常に重要です。
-
実行時パニックの条件の再定義:
If <code>n</code> is negative or larger than <code>m</code> at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
- この文は、引数が変数である場合など、コンパイル時には不正な値が確定できないケースにおいて、実行時に
n
が負であるかm
より大きい場合に引き続きパニックが発生することを明確にしています。これにより、コンパイル時チェックが適用されない動的なシナリオでの安全性が保証されます。
-
具体例の追加:
s := make([]int, 10, 0) // illegal: len(s) > cap(s)
- この新しい例は、
len
がcap
より大きいという不正なmake()
の呼び出しが、コンパイル時に「illegal」(不正)として扱われることを示しています。これは、上記の仕様変更を具体的に示すものです。
この変更は、Go言語のコンパイラがすでに一部の定数引数に対してコンパイル時エラーを報告していたという事実を仕様に反映させ、言語全体の一貫性を向上させるものです。これにより、make()
の挙動が、インデックス式における定数と変数の扱いと同様になり、Go言語の設計原則である「予測可能性」と「シンプルさ」がさらに強化されます。開発者は、より早期にエラーを検出し、より信頼性の高いGoプログラムを記述できるようになります。
関連リンク
- Go言語の仕様書: https://go.dev/ref/spec
- Go言語のIssue 4085: https://github.com/golang/go/issues/4085
- このコミットのGo Gerritレビュー: https://golang.org/cl/6725053
参考にした情報源リンク
- Go言語の公式ドキュメント
- GitHubのGoリポジトリのコミット履歴
- Go言語のIssueトラッカー
- Go言語のメーリングリストアーカイブ (golang-dev)
- Go言語の
make
関数に関する一般的な解説記事 - Go言語の定数に関する解説記事
- Go言語のパニックと回復に関する解説記事