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

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

このコミットは、Go言語のテストスイートの一部である test/nil.go ファイルに対する変更です。具体的には、nil マップに対する delete 操作の挙動変更に伴い、不要になったパニックテストケースを削除しています。

コミット

commit 0df58a4b50b923a220b9fda8ef94bebd5cdc0f9f
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri Dec 14 02:19:33 2012 +0800

    test/nil.go: delete on nil maps no longer panics
    Fix the build.
    
    R=golang-dev
    CC=golang-dev
    https://golang.org/cl/6946044

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

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

元コミット内容

test/nil.go: delete on nil maps no longer panics Fix the build.

変更の背景

このコミットの背景には、Go言語のマップ(map)型における delete 組み込み関数の挙動変更があります。Go 1.1より前のバージョンでは、nil マップに対して delete 関数を呼び出すと、ランタイムパニック(panic)が発生していました。しかし、Go 1.1以降では、nil マップに対する delete 操作はパニックを起こさず、何もしない(no-op)ように変更されました。

この変更は、開発者が delete(m, key) を呼び出す際に、事前に mnil であるかどうかを明示的にチェックする必要がなくなるため、コードの記述を簡素化し、より堅牢にする目的で行われました。nil マップに対する delete が安全になったことで、既存のテストコード test/nil.go 内で nil マップに対する delete がパニックを起こすことを期待していたテストケースが不要となり、ビルドエラーを引き起こす可能性があったため、このコミットで削除されました。

前提知識の解説

Go言語のマップ (map)

Go言語の map は、キーと値のペアを格納するハッシュテーブルの実装です。キーは一意であり、値にアクセスするために使用されます。マップは参照型であり、make 関数で初期化する必要があります。

例:

var m map[string]int // nilマップ
m = make(map[string]int) // 初期化されたマップ
m["apple"] = 1

nil マップ

Go言語において、マップが宣言されただけで make 関数で初期化されていない場合、そのマップは nil 値を持ちます。nil マップは、キーと値のペアを格納するためのメモリが割り当てられていない状態を意味します。

nil マップに対する操作には、以下のような特性があります。

  • 読み取り: nil マップから値を読み取ることは可能で、そのキーのゼロ値が返されます(パニックは発生しない)。
  • 書き込み: nil マップに値を書き込もうとすると、ランタイムパニックが発生します。
  • len: nil マップの長さは0です(パニックは発生しない)。
  • delete: このコミットの変更点であり、Go 1.1以降では nil マップに対する delete はパニックを起こしません。

delete 組み込み関数

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

構文: delete(map, key)

例:

m := make(map[string]int)
m["apple"] = 1
m["banana"] = 2
delete(m, "apple") // "apple"を削除

panicshouldPanic

Go言語の panic は、プログラムの実行を停止させる回復不可能なエラーを示します。通常、予期せぬエラーやプログラマーの論理的な誤りによって発生します。

test/nil.go ファイルには、特定の操作がパニックを引き起こすことをテストするためのヘルパー関数 shouldPanic が含まれています。この関数は、引数として渡された関数が実行されたときにパニックが発生するかどうかを検証します。

技術的詳細

このコミットは、Go言語のバージョン1.1で導入された重要な変更、すなわち「nil マップに対する delete 操作がパニックを起こさなくなった」という挙動の反映です。

Go 1.1より前は、delete(m, key)mnil の場合、プログラムはクラッシュしていました。これは、nil マップがまだメモリを割り当てられていない状態であるため、その構造を変更しようとすることが不正な操作と見なされたためです。

しかし、Go 1.1の設計変更により、delete 関数は nil マップに対して呼び出された場合でも安全に動作するように修正されました。具体的には、delete 関数は内部的に mnil であるかどうかをチェックし、nil であれば何もしない(no-op)で正常に終了するようになりました。これにより、開発者は delete を呼び出す前に if m != nil のような nil チェックを行う必要がなくなり、コードの簡潔性と堅牢性が向上しました。

このコミットは、この言語仕様の変更に合わせて、既存のテストコード test/nil.go を更新するものです。以前のテストでは、nil マップに対する delete がパニックを起こすことを期待して shouldPanic でラップされていましたが、新しい挙動ではパニックが発生しないため、このテストケースはもはや有効ではなく、削除されることになりました。これにより、テストスイートが新しい言語のセマンティクスと一致し、ビルドが正常に完了するようになります。

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

変更は test/nil.go ファイルの maptest() 関数内で行われています。

--- a/test/nil.go
+++ b/test/nil.go
@@ -151,9 +151,6 @@ func maptest() {
 	shouldPanic(func() {
 		m[2] = 3
 	})
-	shouldPanic(func() {
-		delete(m, 2)
-	})
 }

具体的には、以下の3行が削除されました。

	shouldPanic(func() {
		delete(m, 2)
	})

コアとなるコードの解説

削除されたコードは、maptest() 関数内で nil マップ m に対して delete(m, 2) を実行し、それがパニックを引き起こすことを shouldPanic ヘルパー関数で検証していました。

maptest() 関数は、Go言語のマップの様々な挙動、特に nil マップやゼロ値のマップに関する挙動をテストするために設計されています。この関数内で mvar m map[int]int として宣言されており、初期化されていないため nil マップです。

Go 1.1より前のバージョンでは、nil マップに対して delete を呼び出すとランタイムパニックが発生するのが正しい挙動でした。したがって、このテストケースは当時の言語仕様に合致していました。

しかし、Go 1.1で nil マップに対する delete がパニックを起こさずに何もしないように変更されたため、このテストケースはもはやパニックを検出せず、テストが失敗するか、あるいは意図しない挙動を示す可能性がありました。このコミットは、この言語仕様の変更にテストコードを同期させるために、この不要になったテストケースを削除しています。これにより、テストスイートがGo 1.1以降のマップの挙動を正しく反映するようになります。

関連リンク

参考にした情報源リンク