[インデックス 12180] ファイルの概要
このコミットは、Go言語のテストスイート内の複数のテストファイル(test/nil.go
、test/nilptr.go
、test/parentype.go
、test/peano.go
、test/printbig.go
、test/range.go
、test/recover3.go
、test/rename.go
、test/rename1.go
、test/reorder.go
、test/reorder2.go
、test/rune.go
、test/runtime.go
)にドキュメンテーション(コメント)を追加することを目的としています。特に、rename.go
と rename1.go
というファイルについては、以前のドキュメンテーションが不十分であったか、再作業が必要であったことが示唆されています。
コミット
commit 19bab1dc78f1a1398d8e86bda1513b3671995ed7
Author: Rob Pike <r@golang.org>
Date: Fri Feb 24 10:30:39 2012 +1100
test/[n-r]*.go: add documentation
The rename ones needed redoing.
R=golang-dev, bradfitz, rsc
CC=golang-dev
https://golang.org/cl/5698054
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/19bab1dc78f1a1398d8e86bda1513b3671995ed7
元コミット内容
test/[n-r]*.go: add documentation
The rename ones needed redoing.
変更の背景
このコミットの主な背景は、Go言語のテストスイートの可読性と保守性を向上させることです。テストファイルに適切なドキュメンテーションを追加することで、各テストの目的、テスト対象の機能、および期待される動作を明確にすることができます。
特に、rename.go
と rename1.go
に関して「The rename ones needed redoing.(rename関連のものはやり直しが必要だった)」という記述があります。これは、これらのファイルがGo言語の「事前宣言された識別子(predeclared identifiers)」の再宣言(シャドーイング)という、言語仕様の重要な側面をテストしているため、その複雑さから以前のドキュメンテーションが不十分であったか、誤解を招くものであった可能性を示唆しています。テストの意図を正確に伝えるために、より詳細で正確なコメントが必要とされたと考えられます。
Go言語の進化に伴い、テストの網羅性と正確性を維持することは非常に重要です。このコミットは、テストコード自体が自己文書化され、将来の変更やデバッグが容易になるようにするための継続的な取り組みの一環と言えます。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念に関する前提知識が役立ちます。
- Go言語のテストフレームワーク: Go言語は標準で
testing
パッケージを提供しており、テストファイルは通常_test.go
というサフィックスを持ちます。このコミットで変更されているファイルは、Goのテストスイートの一部であり、言語の特定の動作を検証するためのものです。 - 事前宣言された識別子 (Predeclared Identifiers): Go言語には、
int
,bool
,string
,true
,false
,nil
,append
,len
,make
,new
,panic
,print
,println
など、言語仕様によってあらかじめ定義されている識別子があります。これらは組み込み型、組み込み関数、組み込み定数などです。 - 識別子のシャドーイング (Shadowing): Go言語では、スコープ内で事前宣言された識別子と同じ名前の新しい識別子を宣言することができます。これにより、事前宣言された識別子の「シャドーイング」が発生し、そのスコープ内では新しい識別子が優先されます。
rename.go
とrename1.go
は、このシャドーイングの挙動をテストしています。 iota
:iota
はGo言語の特別な事前宣言された定数で、const
ブロック内で連続する整数値を生成するために使用されます。const
ブロックの最初のiota
は0
で、それ以降のconst
宣言ごとに値が1ずつ増加します。nil
:nil
はGo言語のゼロ値の一つで、ポインタ、スライス、マップ、チャネル、関数、インターフェースなどの参照型が何も指していないことを示します。for range
:for range
は、スライス、配列、文字列、マップ、チャネルなどのコレクションを反復処理するためのGo言語の構文です。panic
とrecover
:panic
はGoプログラムの異常終了を引き起こす組み込み関数です。recover
はdefer
された関数内でpanic
から回復するために使用され、プログラムのクラッシュを防ぐことができます。rune
:rune
はGo言語の組み込み型で、Unicodeコードポイントを表すために使用されるint32
のエイリアスです。runtime
パッケージ:runtime
パッケージは、Goランタイムシステムとのインタラクションを可能にする低レベルの関数を提供します。通常、アプリケーション開発者が直接使用することは稀ですが、コンパイラやランタイムのテストでは重要な役割を果たします。
技術的詳細
このコミットでは、主にGo言語のテストファイルにコメントが追加され、一部のファイルではテストロジックの微調整が行われています。
コメント追加のパターン: 多くのファイルでは、ファイルの冒頭にそのテストの目的を簡潔に説明するコメントが追加されています。
test/nil.go
:// Test nil.
test/nilptr.go
:// Test that the implementation catches nil ptr indirection // in a large address space.
test/parentype.go
:// Test that types can be parenthesized.
test/peano.go
:// Test that heavy recursion works. Simple torture test for // segmented stacks: do math in unary by recursion.
test/printbig.go
:// Test that big numbers work as constants and print can print them.
test/range.go
:// Test the 'for range' construct.
test/recover3.go
:// Test recovering from runtime errors.
test/reorder.go
:// Test reordering of assignments.
(以前の "Check reordering of assignments." から変更)test/reorder2.go
:// Test reorderings; derived from fixedbugs/bug294.go.
(以前の "derived from fixedbugs/bug294.go" から変更)test/rune.go
:// Test rune constants, expressions and types. // Compiles but does not run.
test/runtime.go
:// Test that even if a file imports runtime, // it cannot get at the low-level runtime definitions // known to the compiler. For normal packages // the compiler doesn't even record the lower case // functions in its symbol table, but some functions // in runtime are hard-coded into the compiler. // Does not compile.
(以前のコメントから大幅に拡張)
test/rename.go
の変更詳細:
このファイルは、Goの事前宣言された識別子をユーザーが再宣言できることをテストします。
- テスト対象の識別子の拡張:
main
関数内のn
の計算で、以前よりも多くの事前宣言された識別子(append
,complex
,complex64
,complex128
,close
,delete
,error
,imag
,len
,make
,new
,panic
,print
,println
,real
,recover
,rune
,string
など)がconst
として再宣言され、その合計が計算されるようになりました。 const
ブロックの更新:const
ブロックも、新しい識別子に合わせて拡張され、iota
の利用方法が変更されました。以前は各定数に明示的に数値が割り当てられていましたが、変更後はiota
を利用して自動的に連番が割り当てられるようになりました。append = iota
から始まり、各識別子に連続する値が割り当てられます。NUM
という新しい定数が追加され、これは再宣言された識別子の総数を表します。iota = 0
がconst
ブロックの最後に再度宣言されていますが、これはこの特定のテストの文脈でiota
の挙動をリセットまたは検証するためのものと考えられます。
- 合計値の検証ロジックの改善:
n
の合計値の検証が、ハードコードされた数値(27*28/2
)から、NUM*(NUM-1)/2
という動的な計算に変わりました。これは、NUM
が再宣言された識別子の総数を表すため、テストの堅牢性が向上しています。
test/rename1.go
の変更詳細:
このファイルは、再宣言された識別子が元の意味を持たなくなることを検証するテストです。このファイルはコンパイルエラーになることを意図しています。
- コメントの追加:
// Verify that renamed identifiers no longer have their old meaning. // Does not compile.
というコメントが追加され、このテストの目的と、コンパイルエラーが期待されることが明確にされました。 - 型変換の変更:
var y = float(0)
がvar y = float32(0)
に変更されました。元のコードではfloat
が型としてではなく関数として扱われエラーになっていましたが、float32
にすることで、float32
が再宣言された定数として扱われ、型変換として機能しないことをテストしています。// ERROR "cannot call|expected function"
というコメントは残されており、この行が引き続きコンパイルエラーになることを示しています。 const
ブロックの更新:test/rename.go
と同様に、const
ブロックが拡張され、より多くの事前宣言された識別子が再宣言されています。iota
の型エラーテスト:iota = "123"
という行が追加されました。これは、iota
が文字列として再宣言された場合に、a = 1 + iota
の行で型エラー(ERROR "string|incompatible types" "convert iota"
)が発生することをテストしています。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、主にtest/rename.go
とtest/rename1.go
ファイルです。これらのファイルでは、単なるコメントの追加だけでなく、テストロジック自体が拡張・修正されています。
test/rename.go
の変更差分:
--- a/test/rename.go
+++ b/test/rename.go
@@ -4,70 +4,95 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Test that predeclared names can be redeclared by the user.
+
package main
import "fmt"
func main() {
n :=
-\t\tbool +
+\t\tappend +
+\t\t\tbool +
\t\t\tbyte +
-\t\t\tfloat +
+\t\t\tcomplex +
+\t\t\tcomplex64 +
+\t\t\tcomplex128 +
+\t\t\tcap +
+\t\t\tclose +
+\t\t\tdelete +
+\t\t\terror +
+\t\t\tfalse +
\t\t\tfloat32 +
\t\t\tfloat64 +
+\t\t\timag +
\t\t\tint +
\t\t\tint8 +
\t\t\tint16 +
\t\t\tint32 +
\t\t\tint64 +
+\t\t\tlen +
+\t\t\tmake +
+\t\t\tnew +
+\t\t\tnil +
+\t\t\tpanic +
+\t\t\tprint +
+\t\t\tprintln +
+\t\t\treal +
+\t\t\trecover +
+\t\t\trune +
+\t\t\tstring +
+\t\t\ttrue +
\t\t\tuint +
\t\t\tuint8 +
\t\t\tuint16 +
\t\t\tuint32 +
\t\t\tuint64 +
\t\t\tuintptr +
-\t\t\ttrue +
-\t\t\tfalse +
-\t\t\tiota +
-\t\t\tnil +
-\t\t\tcap +
-\t\t\tlen +
-\t\t\tmake +
-\t\t\tnew +
-\t\t\tpanic +
-\t\t\tprint +
-\t\t\tprintln
-\tif n != 27*28/2 {
-\t\tfmt.Println(\"BUG: wrong n\", n, 27*28/2)\n+\t\t\tiota
+\tif n != NUM*(NUM-1)/2 {
+\t\tfmt.Println(\"BUG: wrong n\", n, NUM*(NUM-1)/2)\n \t}\n }\n \n const (\n-\tbool = 1
-\tbyte = 2
-\tfloat = 3
-\tfloat32 = 4
-\tfloat64 = 5
-\tint = 6
-\tint8 = 7
-\tint16 = 8
-\tint32 = 9
-\tint64 = 10
-\tuint = 11
-\tuint8 = 12
-\tuint16 = 13
-\tuint32 = 14
-\tuint64 = 15
-\tuintptr = 16
-\ttrue = 17
-\tfalse = 18
-\tiota = 19
-\tnil = 20
-\tcap = 21
-\tlen = 22
-\tmake = 23
-\tnew = 24
-\tpanic = 25
-\tprint = 26
-\tprintln = 27
+\tappend = iota
+\tbool
+\tbyte
+\tcomplex
+\tcomplex64
+\tcomplex128
+\tcap
+\tclose
+\tdelete
+\terror
+\tfalse
+\tfloat32
+\tfloat64
+\timag
+\tint
+\tint8
+\tint16
+\tint32
+\tint64
+\tlen
+\tmake
+\tnew
+\tnil
+\tpanic
+\tprint
+\tprintln
+\treal
+\trecover
+\trune
+\tstring
+\ttrue
+\tuint
+\tuint8
+\tuint16
+\tuint32
+\tuint64
+\tuintptr
+\tNUM
+\tiota = 0
)
test/rename1.go
の変更差分:
--- a/test/rename1.go
+++ b/test/rename1.go
@@ -4,11 +4,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Verify that renamed identifiers no longer have their old meaning.
+// Does not compile.
+
package main
func main() {\n \tvar n byte // ERROR \"not a type|expected type\"\n-\tvar y = float(0) // ERROR \"cannot call|expected function\"\n+\tvar y = float32(0) // ERROR \"cannot call|expected function\"\n \tconst (\n \t\ta = 1 + iota // ERROR \"string|incompatible types\" \"convert iota\"\n \t)\n@@ -16,31 +19,43 @@ func main() {\n }\n \n const (\n-\tbool = 1
-\tbyte = 2
-\tfloat = 3
-\tfloat32 = 4
-\tfloat64 = 5
-\tint = 6
-\tint8 = 7
-\tint16 = 8
-\tint32 = 9
-\tint64 = 10
-\tuint = 11
-\tuint8 = 12
-\tuint16 = 13
-\tuint32 = 14
-\tuint64 = 15
-\tuintptr = 16
-\ttrue = 17
-\tfalse = 18
-\tiota = \"abc\"\n-\tnil = 20
-\tcap = 21
-\tlen = 22
-\tmake = 23
-\tnew = 24
-\tpanic = 25
-\tprint = 26
-\tprintln = 27
+\tappend = iota
+\tbool
+\tbyte
+\tcomplex
+\tcomplex64
+\tcomplex128
+\tcap
+\tclose
+\tdelete
+\terror
+\tfalse
+\tfloat32
+\tfloat64
+\timag
+\tint
+\tint8
+\tint16
+\tint32
+\tint64
+\tlen
+\tmake
+\tnew
+\tnil
+\tpanic
+\tprint
+\tprintln
+\treal
+\trecover
+\trune
+\tstring
+\ttrue
+\tuint
+\tuint8
+\tuint16
+\tuint32
+\tuint64
+\tuintptr
+\tNUM
+\tiota = \"123\"\n )
コアとなるコードの解説
test/rename.go
の解説:
このテストは、Go言語の重要な特性である「事前宣言された識別子のシャドーイング」を検証します。Goでは、int
やlen
のような組み込みの識別子と同じ名前の定数や変数をユーザーが定義できます。このテストでは、const
ブロック内で多数の事前宣言された識別子を定数として再定義し、それらの定数値を合計しています。
- 識別子の拡張と
iota
の利用: 以前は一部の識別子のみがテストされていましたが、この変更により、より多くの組み込み識別子(append
,complex
など)がテスト対象に追加されました。const
ブロックでiota
を使用することで、各定数に自動的に連続した整数値が割り当てられ、テストコードの簡潔性と拡張性が向上しています。 NUM
定数の導入:NUM
という定数が導入され、これは再宣言された識別子の総数を表します。これにより、合計値の検証ロジックがNUM*(NUM-1)/2
という動的な計算に変わり、テスト対象の識別子が増減しても、期待される合計値を手動で更新する必要がなくなりました。これは、1からNまでの整数の合計を計算するガウスの公式(N * (N + 1) / 2)に似ていますが、iota
が0から始まるため、NUM
個の要素の合計はNUM*(NUM-1)/2
となります(0からNUM-1までの合計)。iota = 0
の再宣言:const
ブロックの最後にiota = 0
が再度宣言されています。これは、このconst
ブロック内でのiota
の挙動をリセットし、特定のテストシナリオを検証するためのものです。
このテストは、Goコンパイラが事前宣言された識別子のシャドーイングを正しく処理し、ユーザー定義の識別子が優先されることを保証するために不可欠です。
test/rename1.go
の解説:
このテストは、test/rename.go
とは対照的に、再宣言された識別子が元の組み込みの意味を完全に失うことを検証します。このファイルは意図的にコンパイルエラーを引き起こすように設計されており、// ERROR
コメントで期待されるエラーメッセージが示されています。
// Does not compile.
コメント: このコメントは、このファイルがコンパイルに失敗することを明確に示しており、テストの意図を理解する上で非常に重要です。var y = float32(0)
の変更: 以前はfloat(0)
でしたが、float32(0)
に変更されました。この変更の意図は、float32
がconst
ブロックで定数として再宣言されているため、float32(0)
が型変換ではなく、定数float32
を関数のように呼び出そうとしていると解釈され、コンパイルエラーになることをテストすることです。これは、再宣言された識別子が元の型としての意味を失うことを示しています。iota
の型エラーテスト:iota = "123"
という行は、iota
が文字列として再宣言された場合に、その後のa = 1 + iota
の計算で型不一致のエラーが発生することをテストしています。これは、再宣言されたiota
がもはや数値としての意味を持たないことを示しています。
これらの変更は、Go言語のコンパイラが識別子のスコープとシャドーイングのルールを厳密に適用し、開発者が意図しない挙動に遭遇しないようにするための重要なテストケースです。
関連リンク
- Go Gerrit Change-ID: https://golang.org/cl/5698054
参考にした情報源リンク
- Go言語の公式ドキュメンテーション (Go Language Specification): https://go.dev/ref/spec
- Go言語の組み込み関数と型に関するドキュメンテーション: https://go.dev/pkg/builtin/
- Go言語の
iota
に関する解説 (例: Go by Example - Constants): https://gobyexample.com/constants - Go言語の
panic
とrecover
に関する解説 (例: Go by Example - Panics): https://gobyexample.com/panics - Go言語のテストに関するドキュメンテーション: https://go.dev/pkg/testing/