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

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

このコミットは、Go言語のテストスイート内の複数のテストファイル(test/nil.gotest/nilptr.gotest/parentype.gotest/peano.gotest/printbig.gotest/range.gotest/recover3.gotest/rename.gotest/rename1.gotest/reorder.gotest/reorder2.gotest/rune.gotest/runtime.go)にドキュメンテーション(コメント)を追加することを目的としています。特に、rename.gorename1.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.gorename1.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.gorename1.go は、このシャドーイングの挙動をテストしています。
  • iota: iotaはGo言語の特別な事前宣言された定数で、constブロック内で連続する整数値を生成するために使用されます。constブロックの最初のiota0で、それ以降のconst宣言ごとに値が1ずつ増加します。
  • nil: nilはGo言語のゼロ値の一つで、ポインタ、スライス、マップ、チャネル、関数、インターフェースなどの参照型が何も指していないことを示します。
  • for range: for rangeは、スライス、配列、文字列、マップ、チャネルなどのコレクションを反復処理するためのGo言語の構文です。
  • panicrecover: panicはGoプログラムの異常終了を引き起こす組み込み関数です。recoverdeferされた関数内で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 = 0constブロックの最後に再度宣言されていますが、これはこの特定のテストの文脈で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.gotest/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では、intlenのような組み込みの識別子と同じ名前の定数や変数をユーザーが定義できます。このテストでは、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)に変更されました。この変更の意図は、float32constブロックで定数として再宣言されているため、float32(0)が型変換ではなく、定数float32を関数のように呼び出そうとしていると解釈され、コンパイルエラーになることをテストすることです。これは、再宣言された識別子が元の型としての意味を失うことを示しています。
  • iotaの型エラーテスト: iota = "123"という行は、iotaが文字列として再宣言された場合に、その後のa = 1 + iotaの計算で型不一致のエラーが発生することをテストしています。これは、再宣言されたiotaがもはや数値としての意味を持たないことを示しています。

これらの変更は、Go言語のコンパイラが識別子のスコープとシャドーイングのルールを厳密に適用し、開発者が意図しない挙動に遭遇しないようにするための重要なテストケースです。

関連リンク

参考にした情報源リンク