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

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

このコミットは、Go言語の組み込み関数 delete() のコメントを修正し、nil マップに対する delete() の挙動がパニックではなくno-op(何もしない)になったことを反映しています。

コミット

commit 0b50a5dad78193fecae52f18a01df928c229eb32
Author: Jingcheng Zhang <diogin@gmail.com>
Date:   Fri Dec 14 09:13:42 2012 -0800

    builtin: correct comment on builtin function delete().
    
    Delete on a nil map is now a no-op.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/6938054
---
 src/pkg/builtin/builtin.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pkg/builtin/builtin.go b/src/pkg/builtin/builtin.go
index a30943b894..91d263a623 100644
--- a/src/pkg/builtin/builtin.go
+++ b/src/pkg/builtin/builtin.go
@@ -124,8 +124,8 @@ func append(slice []Type, elems ...Type) []Type
 func copy(dst, src []Type) int
 
 // The delete built-in function deletes the element with the specified key
-// (m[key]) from the map. If there is no such element, delete is a no-op.\n-// If m is nil, delete panics.
+// (m[key]) from the map. If m is nil or there is no such element, delete\n+// is a no-op.
 func delete(m map[Type]Type1, key Type)
 
 // The len built-in function returns the length of v, according to its type:\n

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/0b50a5dad78193fecae52f18a01df928c229eb32

元コミット内容

builtin: correct comment on builtin function delete().

Delete on a nil map is now a no-op.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6938054

変更の背景

このコミットの背景には、Go言語のマップ型における delete 組み込み関数の挙動の変更があります。以前のGoのバージョンでは、nil マップに対して delete 関数を呼び出すとパニック(ランタイムエラー)が発生していました。しかし、Go言語の設計思想として、一般的な操作においては nil 値に対する操作が安全であるべきという考え方があります。例えば、nil スライスへの appendnil チャネルからの読み取りなどはパニックを起こしません。

マップの場合、nil マップからの読み取りはゼロ値を返し、パニックは発生しません。この一貫性を保つため、nil マップに対する delete 操作もパニックではなく、何もしない(no-op)という挙動に変更されました。この変更により、開発者は delete を呼び出す前にマップが nil かどうかを明示的にチェックする必要がなくなり、コードの記述がより簡潔かつ堅牢になります。

このコミット自体は、実際の delete 関数の実装を変更するものではなく、その挙動変更に伴って、src/pkg/builtin/builtin.go 内の delete 関数のコメントを、新しい挙動に合わせて更新することが目的です。これは、Go言語のドキュメントと実際の挙動との間に齟齬がないようにするための重要な修正です。

前提知識の解説

Go言語のマップ (map)

Go言語のマップは、キーと値のペアを格納するハッシュテーブルの実装です。キーは一意であり、値にマッピングされます。マップは make 関数で初期化するか、マップリテラルを使用して作成します。

// マップの宣言と初期化
var m map[string]int // nilマップ
m = make(map[string]int) // 空のマップ
m2 := map[string]int{"apple": 1, "banana": 2} // マップリテラル

nil マップ

Goにおいて、マップ型の変数を宣言しただけで初期化しない場合、その変数は nil マップとなります。nil マップは、内部的にデータ構造が割り当てられていない状態を指します。

  • nil マップへの書き込み: nil マップに要素を追加しようとすると、ランタイムパニックが発生します。これは、データ構造が存在しないため、要素を格納する場所がないためです。
  • nil マップからの読み取り: nil マップから要素を読み取ろうとすると、パニックは発生せず、その値型のゼロ値が返されます。例えば、map[string]int の場合、int のゼロ値である 0 が返されます。
  • nil マップの長さ: len(nilMap)0 を返します。

delete 組み込み関数

delete はGo言語に組み込まれている関数で、マップから指定されたキーの要素を削除するために使用されます。

func delete(m map[Type]Type1, key Type)
  • m: 要素を削除する対象のマップ。
  • key: 削除する要素のキー。

delete 関数は、指定されたキーがマップに存在しない場合でもパニックを起こしません。その場合、単に何もしません(no-op)。

no-op (No Operation)

no-opとは、「何もしない操作」を意味します。プログラミングにおいては、特定の条件が満たされた場合や、エラーではないが処理を行う必要がない場合に、プログラムが何もせず、しかしエラーも発生させずに続行する挙動を指します。この文脈では、nil マップに対して delete を呼び出しても、プログラムがクラッシュすることなく、単に要素の削除処理が行われないことを意味します。

技術的詳細

このコミットの技術的な詳細の中心は、Go言語の delete 組み込み関数が nil マップに対してどのように振る舞うかという仕様変更と、それに対応するドキュメントの更新です。

変更前の挙動とコメント

変更前は、delete 関数が nil マップに対して呼び出されるとパニックが発生するという仕様でした。これに伴い、src/pkg/builtin/builtin.go 内の delete 関数のコメントは以下のようになっていました。

// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If there is no such element, delete is a no-op.
// If m is nil, delete panics.

このコメントの最後の行「If m is nil, delete panics.」が、nil マップに対する delete がパニックを引き起こすことを明示していました。

変更後の挙動とコメント

Go言語の進化の過程で、nil マップに対する delete の挙動が変更され、パニックではなくno-opとなるように仕様が改定されました。この変更は、Goの設計原則である「ゼロ値の有用性」や「安全なデフォルト」に沿ったものです。nil マップからの読み取りがパニックを起こさないのと同様に、nil マップからの削除も安全に行えるようになりました。

この仕様変更を受けて、コメントも以下のように更新されました。

// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If m is nil or there is no such element, delete
// is a no-op.

変更点としては、「If m is nil, delete panics.」が削除され、「If m is nil or there is no such element, delete is a no-op.」という記述に置き換えられました。これにより、nil マップの場合でも、キーが存在しない場合と同様に delete がno-opとして振る舞うことが明確に示されています。

影響と利点

この変更は、Go言語のコードの堅牢性と簡潔性を向上させます。

  • 堅牢性: 開発者は delete を呼び出す前にマップが nil かどうかを明示的にチェックする必要がなくなります。これにより、nil マップに対する delete 呼び出しが原因で予期せぬパニックが発生するリスクが減少します。
  • 簡潔性: if m != nil { delete(m, key) } のような冗長なチェックが不要になり、コードがよりシンプルになります。

この変更は、Go言語の標準ライブラリやアプリケーションコード全体にわたって、より安全で予測可能なマップ操作を可能にするための重要な一歩でした。

コアとなるコードの変更箇所

変更は src/pkg/builtin/builtin.go ファイルの delete 関数のコメント部分にあります。

--- a/src/pkg/builtin/builtin.go
+++ b/src/pkg/builtin/builtin.go
@@ -124,8 +124,8 @@ func append(slice []Type, elems ...Type) []Type
 func copy(dst, src []Type) int
 
 // The delete built-in function deletes the element with the specified key
-// (m[key]) from the map. If there is no such element, delete is a no-op.\n-// If m is nil, delete panics.
+// (m[key]) from the map. If m is nil or there is no such element, delete\n+// is a no-op.
 func delete(m map[Type]Type1, key Type)
 
 // The len built-in function returns the length of v, according to its type:\n

具体的には、以下の2行が変更されています。

  • 削除された行: // If m is nil, delete panics.
  • 追加された行: // is a no-op. (前の行と合わせて If m is nil or there is no such element, delete is a no-op. となる)

コアとなるコードの解説

このコミットにおけるコアとなるコードの変更は、Go言語の組み込み関数 delete のドキュメンテーションコメントの修正です。実際の delete 関数のロジック自体は変更されていません。この変更は、Go言語のマップに対する delete 関数の挙動が、nil マップの場合にパニックを起こすのではなく、何もしない(no-op)ように変更されたという、言語仕様の変更を反映するためのものです。

src/pkg/builtin/builtin.go ファイルは、Go言語の組み込み関数(append, copy, delete, len など)の宣言と、それらの関数のドキュメンテーションコメントを定義しているファイルです。これらのコメントは、Goの公式ドキュメントや go doc コマンドで表示される情報源となります。

変更前は、delete 関数のコメントには「If m is nil, delete panics.(もし mnil なら、delete はパニックを起こす)」と記述されていました。これは、当時の delete 関数の実際の挙動を正確に反映していました。

しかし、Go言語の進化に伴い、nil マップに対する delete の挙動が変更され、パニックではなくno-opとなるように仕様が改定されました。この変更は、Goの設計原則である「ゼロ値の有用性」に沿ったもので、nil マップからの読み取りがパニックを起こさないのと同様に、nil マップからの削除も安全に行えるようにするためです。

このコミットでは、この言語仕様の変更に合わせて、コメントの記述を「If m is nil or there is no such element, delete is a no-op.(もし mnil であるか、そのような要素が存在しない場合、delete はno-opである)」に修正しています。これにより、Goのドキュメントが常に最新の言語仕様と一致するように保たれ、開発者が誤解するのを防ぎます。

この修正は、Go言語の安定性と信頼性を維持するために、ドキュメンテーションが実際の挙動と同期していることの重要性を示しています。

関連リンク

参考にした情報源リンク