Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14947] ファイルの概要

このコミットは、Go言語の公式仕様書である doc/go_spec.html における記述の修正です。具体的には、nilmap 型に対する 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 に、nilmap 型に対しても cap 関数が適用されるかのような誤解を招く記述が存在したことがあります。Go言語において、len 関数はスライス、マップ、チャネルの要素数を返すのに対し、cap 関数はスライスやチャネルの容量(メモリ割り当ての最大値)を返します。しかし、map 型には capacity の概念がありません。map は動的にサイズが変更されるデータ構造であり、その内部実装はハッシュテーブルに基づいているため、スライスやチャネルのような固定された容量を持つわけではありません。

この誤解を招く記述は、Go言語の学習者や開発者にとって混乱の原因となる可能性がありました。コミットメッセージにある Fixes #4682 は、この問題がGoのIssueトラッカーで報告され、その修正としてこのコミットが作成されたことを示しています。この修正により、Go言語の公式仕様がより正確になり、map の特性に関する誤解が解消されることが期待されます。

前提知識の解説

Go言語における nil

Go言語において、nil はゼロ値の一種であり、ポインタ、スライス、マップ、チャネル、関数、インターフェースなどの参照型が何も指していない状態を表します。nil の参照型は、メモリが割り当てられていない状態を意味します。

len 関数と cap 関数

Go言語には、組み込み関数として lencap が存在します。

  • len(v):

    • スライス、文字列、マップ、チャネル、配列、配列ポインタの要素数(長さ)を返します。
    • nil スライス、nil マップ、nil チャネルの場合、len0 を返します。
  • cap(v):

    • スライスまたはチャネルの容量(capacity)を返します。容量とは、再割り当てなしで格納できる要素の最大数です。
    • nil スライスや nil チャネルの場合、cap0 を返します。
    • 重要: 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.htmlLength 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 型の変数に適用しようとすると、コンパイルエラーが発生します。

この誤解を招く記述を修正するため、コミットではこの一文を二つに分割し、mapcapacity が適用されないことを明確にしました。

変更後の記述は以下の通りです。

<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>

この修正により、

  1. nil のスライス、マップ、チャネルの「長さ」が 0 であること。
  2. 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)