[インデックス 14947] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
における記述の修正です。具体的には、nil
の map
型に対する cap
(capacity) 関数の適用に関する誤った記述を訂正し、map
には capacity
の概念が存在しないことを明確にしています。
コミット
- コミットハッシュ:
a0b5b46ae47d2df1f8ed3d640b220c67e7ccc0d9
- 作者: Shenghou Ma minux.ma@gmail.com
- コミット日時: 2013年1月22日 火曜日 03:18:20 +0800
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a0b5b46ae47d2df1f8ed3d640b220c67e7ccc0d9
元コミット内容
doc/go_spec: cap doesn't apply to maps
Fixes #4682.
R=golang-dev, adg, dave
CC=golang-dev
https://golang.org/cl/7094062
変更の背景
この変更の背景には、Go言語の仕様書 doc/go_spec.html
に、nil
の map
型に対しても cap
関数が適用されるかのような誤解を招く記述が存在したことがあります。Go言語において、len
関数はスライス、マップ、チャネルの要素数を返すのに対し、cap
関数はスライスやチャネルの容量(メモリ割り当ての最大値)を返します。しかし、map
型には capacity
の概念がありません。map
は動的にサイズが変更されるデータ構造であり、その内部実装はハッシュテーブルに基づいているため、スライスやチャネルのような固定された容量を持つわけではありません。
この誤解を招く記述は、Go言語の学習者や開発者にとって混乱の原因となる可能性がありました。コミットメッセージにある Fixes #4682
は、この問題がGoのIssueトラッカーで報告され、その修正としてこのコミットが作成されたことを示しています。この修正により、Go言語の公式仕様がより正確になり、map
の特性に関する誤解が解消されることが期待されます。
前提知識の解説
Go言語における nil
Go言語において、nil
はゼロ値の一種であり、ポインタ、スライス、マップ、チャネル、関数、インターフェースなどの参照型が何も指していない状態を表します。nil
の参照型は、メモリが割り当てられていない状態を意味します。
len
関数と cap
関数
Go言語には、組み込み関数として len
と cap
が存在します。
-
len(v)
:- スライス、文字列、マップ、チャネル、配列、配列ポインタの要素数(長さ)を返します。
nil
スライス、nil
マップ、nil
チャネルの場合、len
は0
を返します。
-
cap(v)
:- スライスまたはチャネルの容量(capacity)を返します。容量とは、再割り当てなしで格納できる要素の最大数です。
nil
スライスやnil
チャネルの場合、cap
は0
を返します。- 重要:
map
型にはcap
関数は適用されません。map
は動的にサイズが拡張されるため、固定された容量という概念がありません。
スライス、マップ、チャネルの特性
-
スライス (Slice):
- 配列の一部を参照する動的なビューです。
len
は現在含まれる要素の数、cap
は基底配列の残りの要素を含めてスライスが保持できる最大要素数を表します。nil
スライスは長さも容量も0
です。
-
マップ (Map):
- キーと値のペアを格納する順序付けされていないコレクションです。
len
はマップ内のキーと値のペアの数を返します。map
にはcap
の概念がありません。map
は必要に応じて自動的にサイズを調整します。nil
マップは長さが0
です。nil
マップへの書き込みはランタイムパニックを引き起こします。
-
チャネル (Channel):
- ゴルーチン間で値を送受信するための通信メカニズムです。
len
はチャネル内のキューに入っている要素の数を返します。cap
はチャネルのバッファ容量(バッファリングされたチャネルの場合)を返します。nil
チャネルは長さも容量も0
です。
技術的詳細
このコミットは、Go言語の仕様書 doc/go_spec.html
の Length and capacity
セクションにおける記述の正確性を向上させることを目的としています。
変更前の記述は以下の通りでした。
<p>
The length and capacity of a <code>nil</code> slice, map, or channel are 0.
</p>
この記述は、「nil
のスライス、マップ、またはチャネルの長さと容量は 0
である」と述べています。しかし、前述の通り、Go言語の map
型には capacity
の概念がありません。cap
関数を map
型の変数に適用しようとすると、コンパイルエラーが発生します。
この誤解を招く記述を修正するため、コミットではこの一文を二つに分割し、map
に capacity
が適用されないことを明確にしました。
変更後の記述は以下の通りです。
<p>
The length of a <code>nil</code> slice, map or channel is 0.<br>
The capacity of a <code>nil</code> slice and channel is 0.
</p>
この修正により、
nil
のスライス、マップ、チャネルの「長さ」が0
であること。nil
のスライスとチャネルの「容量」が0
であること。 が明確に区別され、map
にはcapacity
の概念がないことが暗黙的に示されるようになりました。これにより、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 January 18, 2013",
+ "Subtitle": "Version of January 21, 2013",
"Path": "/ref/spec"
}-->
@@ -4922,7 +4922,8 @@ At any time the following relationship holds:\n </pre>\n \n <p>\n-The length and capacity of a <code>nil</code> slice, map, or channel are 0.\n+The length of a <code>nil</code> slice, map or channel is 0.<br>\n+The capacity of a <code>nil</code> slice and channel is 0.\n </p>\n \n <p>\n```
具体的には、以下の行が変更されました。
* `Subtitle` の日付が `January 18, 2013` から `January 21, 2013` に更新されました。これは仕様書のバージョン管理の一環です。
* `The length and capacity of a <code>nil</code> slice, map, or channel are 0.` という行が削除されました。
* 代わりに、以下の2行が追加されました。
* `The length of a <code>nil</code> slice, map or channel is 0.`
* `The capacity of a <code>nil</code> slice and channel is 0.`
## コアとなるコードの解説
このコミットの核心は、Go言語の仕様書における `len` と `cap` 関数の適用範囲に関する記述の正確性を高めることです。
変更前の記述 `The length and capacity of a <code>nil</code> slice, map, or channel are 0.` は、一見すると簡潔ですが、`map` に `capacity` の概念がないというGo言語の重要な特性を見落としていました。Go言語の `cap` 関数は、スライスとチャネルにのみ適用され、`map` には適用されません。もし `map` に対して `cap` を呼び出そうとすると、コンパイル時にエラーが発生します。
新しい記述では、この点を明確にするために、`len` と `cap` の適用対象を分離しました。
1. `The length of a <code>nil</code> slice, map or channel is 0.`
* これは、`nil` のスライス、マップ、チャネルのいずれも、その「長さ」が `0` であるという事実を正確に述べています。`len` 関数はこれらすべての型に適用可能です。
2. `The capacity of a <code>nil</code> slice and channel is 0.`
* これは、`nil` のスライスとチャネルの「容量」が `0` であることを明確にしています。ここで `map` がリストから除外されていることが重要です。これにより、`map` には `capacity` の概念がないことが読者に正しく伝わります。
この修正は、Go言語の仕様書が、言語の動作を正確かつ誤解なく記述するというその役割を果たす上で非常に重要です。これにより、開発者はGo言語のデータ構造の特性をより正確に理解できるようになります。
## 関連リンク
* Go言語の公式仕様書: [https://golang.org/ref/spec](https://golang.org/ref/spec)
* このコミットに関連するGoのコードレビューツール (Gerrit) のチェンジリスト: [https://golang.org/cl/7094062](https://golang.org/cl/7094062)
## 参考にした情報源リンク
* The Go Programming Language Specification - Length and capacity: [https://golang.org/ref/spec#Length_and_capacity](https://golang.org/ref/spec#Length_and_capacity) (現在の仕様書の内容)
* Go by Example: `len` and `cap`: [https://gobyexample.com/len-cap](https://gobyexample.com/len-cap)
* A Tour of Go - Slices: [https://go.dev/tour/moretypes/7](https://go.dev/tour/moretypes/7)
* A Tour of Go - Maps: [https://go.dev/tour/moretypes/19](https://go.dev/tour/moretypes/19)
* A Tour of Go - Channels: [https://go.dev/tour/concurrency/2](https://go.dev/tour/concurrency/2)