[インデックス 15197] ファイルの概要
このコミットは、Go言語の標準ライブラリである container/list
パッケージに、その基本的な使用方法を示す新しい例を追加するものです。具体的には、example_test.go
というファイルが新規作成され、container/list
を用いてリストの作成、要素の追加(先頭、末尾、指定要素の前、指定要素の後)、およびリストのイテレーション(走査)を行うコードが記述されています。この例は、go test
コマンド実行時に自動的にテストとして実行され、その出力が期待される出力と一致するかどうかを検証する形式で提供されます。
コミット
commit 66c96f1abc6e6fc944b07305e975d497a61ff83e
Author: Andrew Gerrand <adg@golang.org>
Date: Mon Feb 11 17:59:52 2013 +1100
container/list: add package example
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/7306078
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/66c96f1abc6e6fc944b07305e975d497a61ff83e
元コミット内容
このコミットは、container/list
パッケージにパッケージ例を追加します。
変更の背景
Go言語の標準ライブラリは、その機能と使用方法を明確に理解してもらうために、豊富なドキュメントと例を提供しています。container/list
パッケージは、Go言語で双方向連結リストを実装するための基本的なデータ構造を提供しますが、その使用方法を具体的に示すコード例が不足していた可能性があります。
このコミットの目的は、container/list
パッケージの基本的な操作(リストの作成、要素の追加、要素の走査)を簡潔かつ明確に示す Example
関数を追加することです。これにより、開発者がこのパッケージをどのように利用すればよいかを迅速に理解できるようになり、ライブラリの使いやすさが向上します。特に、example_test.go
ファイルに Example
関数を記述することで、Goのテストフレームワークが提供する特別な機能を利用し、コード例が常にコンパイル可能で、期待される出力を生成することを確認できます。これは、ドキュメントの正確性と信頼性を維持する上で非常に重要です。
前提知識の解説
Go言語の container/list
パッケージ
container/list
パッケージは、Go言語で双方向連結リスト(doubly linked list)を実装するためのデータ構造を提供します。連結リストは、配列とは異なり、要素がメモリ上で連続して配置される必要がなく、各要素が次の要素(および双方向リストの場合は前の要素)へのポインタを持つことで連結されます。これにより、リストの途中への要素の挿入や削除が効率的に行えるという利点があります。
container/list
パッケージの主要な型とメソッドは以下の通りです。
list.List
: 双方向連結リストを表す構造体です。list.New()
: 新しい空のリストを作成し、そのポインタを返します。l.PushFront(v interface{}) *Element
: リストの先頭に要素v
を追加します。追加された要素を表す*Element
を返します。l.PushBack(v interface{}) *Element
: リストの末尾に要素v
を追加します。追加された要素を表す*Element
を返します。l.InsertBefore(v interface{}, mark *Element) *Element
:mark
で指定された要素の前に要素v
を挿入します。l.InsertAfter(v interface{}, mark *Element) *Element
:mark
で指定された要素の後に要素v
を挿入します。l.Front() *Element
: リストの最初の要素を返します。リストが空の場合はnil
を返します。l.Back() *Element
: リストの最後の要素を返します。リストが空の場合はnil
を返します。e.Next() *Element
: 現在の要素e
の次の要素を返します。次の要素がない場合はnil
を返します。e.Prev() *Element
: 現在の要素e
の前の要素を返します。前の要素がない場合はnil
を返します。e.Value interface{}
: 要素e
に格納されている実際の値です。interface{}
型であるため、任意の型の値を格納できますが、取り出す際には型アサーションが必要です。
Go言語の _test.go
ファイルと Example
関数
Go言語では、テストコードは通常、テスト対象のソースファイルと同じディレクトリに _test.go
というサフィックスを持つファイルとして配置されます。Goのテストフレームワークは、これらのファイルを自動的に検出し、go test
コマンドで実行します。
_test.go
ファイル内には、通常のテスト関数(TestXxx
)、ベンチマーク関数(BenchmarkXxx
)、そして例示関数(ExampleXxx
)を記述できます。
ExampleXxx
関数: この関数は、特定のパッケージ、関数、型、またはメソッドの使用例を示すために使用されます。Example
関数は、その関数名がExample
で始まり、その後に説明的な名前が続く必要があります(例:Example()
,ExampleList_PushBack()
,Example_MyFunction()
)。- 出力の検証:
Example
関数の特別な機能は、その標準出力(fmt.Println
などで出力される内容)が、関数コメント内の// Output:
コメントブロックに記述された内容と一致するかどうかをgo test
が自動的に検証することです。これにより、コード例が常に正しく動作し、期待される出力を生成することが保証されます。 - ドキュメントへの組み込み:
Example
関数は、go doc
コマンドや Goの公式ドキュメントサイト(pkg.go.devなど)で、対応するパッケージや関数のドキュメントに自動的に組み込まれて表示されます。これにより、開発者はコード例を直接ドキュメントから参照でき、理解を深めることができます。
- 出力の検証:
このコミットで追加される Example()
関数は、container/list
パッケージの基本的な使用方法を簡潔に示し、その出力が期待通りであることを自動的に検証することで、パッケージのドキュメントと信頼性を向上させる役割を果たします。
技術的詳細
このコミットは、src/pkg/container/list/example_test.go
という新しいファイルを追加します。このファイルは、list_test
パッケージに属しており、これはテスト対象の list
パッケージとは異なるパッケージ名です。Goの慣習として、テスト対象のパッケージの内部実装に依存しない「外部テスト」を書く場合、_test
サフィックスを付けたパッケージ名を使用します。これにより、テストコードがパッケージの公開APIのみを使用していることを保証できます。
ファイル内で定義されている Example()
関数は、以下のステップで container/list
パッケージの機能を示します。
- リストの初期化:
l := list.New()
を呼び出して、新しい空の双方向連結リストを作成します。 - 要素の追加:
e4 := l.PushBack(4)
: リストの末尾に値4
を追加します。追加された要素へのポインタe4
を保持します。e1 := l.PushFront(1)
: リストの先頭に値1
を追加します。追加された要素へのポインタe1
を保持します。l.InsertBefore(3, e4)
:e4
(値4
) の前に値3
を挿入します。この時点でリストは[1, 3, 4]
のようになります。l.InsertAfter(2, e1)
:e1
(値1
) の後に値2
を挿入します。この時点でリストは[1, 2, 3, 4]
のようになります。
- リストの走査:
for e := l.Front(); e != nil; e = e.Next() { ... }
ループを使用して、リストの先頭から末尾までを走査します。l.Front()
: リストの最初の要素を取得します。e != nil
: 現在の要素がnil
でない限りループを続けます(リストの末尾に達するまで)。e = e.Next()
: 次のイテレーションのために、現在の要素を次の要素に進めます。fmt.Println(e.Value)
: 各要素のValue
フィールド(interface{}
型)を標準出力に出力します。
- 期待される出力の指定:
// Output:
コメントブロックに、このExample
関数が実行されたときに標準出力に表示されるべき内容が記述されています。go test
はこのブロックの内容と実際の出力を比較し、一致しない場合はテストを失敗させます。
この例は、container/list
の基本的なAPIを網羅しており、特に PushFront
, PushBack
, InsertBefore
, InsertAfter
といった要素の追加メソッド、および Front
, Next
, Value
を用いたリストの走査方法を明確に示しています。
コアとなるコードの変更箇所
diff --git a/src/pkg/container/list/example_test.go b/src/pkg/container/list/example_test.go
new file mode 100644
index 0000000000..7361212d73
--- /dev/null
+++ b/src/pkg/container/list/example_test.go
@@ -0,0 +1,30 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package list_test
+
+import (
+ "container/list"
+ "fmt"
+)
+
+func Example() {
+ // Create a new list and put some numbers in it.
+ l := list.New()
+ e4 := l.PushBack(4)
+ e1 := l.PushFront(1)
+ l.InsertBefore(3, e4)
+ l.InsertAfter(2, e1)
+
+ // Iterate through list and and print its contents.
+ for e := l.Front(); e != nil; e = e.Next() {
+ fmt.Println(e.Value)
+ }
+
+ // Output:
+ // 1
+ // 2
+ // 3
+ // 4
+}
コアとなるコードの解説
上記のコードは、container/list
パッケージの基本的な使用例を簡潔に示しています。
-
パッケージ宣言とインポート:
package list_test
: このファイルがlist
パッケージの外部テストであることを示します。import ("container/list", "fmt")
:container/list
パッケージと、標準出力を行うためのfmt
パッケージをインポートしています。
-
Example()
関数:l := list.New()
: 新しい空のリストl
を作成します。e4 := l.PushBack(4)
: リストの末尾に4
を追加し、その要素へのポインタe4
を取得します。e1 := l.PushFront(1)
: リストの先頭に1
を追加し、その要素へのポインタe1
を取得します。この時点でのリストは[1, 4]
です。l.InsertBefore(3, e4)
:e4
(値4
) の前に3
を挿入します。リストは[1, 3, 4]
となります。l.InsertAfter(2, e1)
:e1
(値1
) の後に2
を挿入します。リストは[1, 2, 3, 4]
となります。for e := l.Front(); e != nil; e = e.Next() { fmt.Println(e.Value) }
: リストの先頭から順に要素を走査し、各要素の値を新しい行に出力します。e.Value
はinterface{}
型なので、fmt.Println
がその値を適切に表示します。// Output:
ブロック: このコメントブロックは、go test
がこのExample
関数の出力を検証するために使用します。この例では、1
,2
,3
,4
がそれぞれ新しい行に出力されることを期待しています。
このコードは、container/list
パッケージの主要なAPIを効果的にデモンストレーションしており、Go言語の Example
関数の慣習に従って、ドキュメントとテストの両方の役割を果たしています。
関連リンク
- Go言語
container/list
パッケージのドキュメント: https://pkg.go.dev/container/list - Go言語のテストに関する公式ドキュメント: https://go.dev/blog/testing
- Go言語の
Example
関数に関する公式ドキュメント: https://go.dev/blog/examples
参考にした情報源リンク
- https://github.com/golang/go/commit/66c96f1abc6e6fc944b07305e975d497a61ff83e
- https://golang.org/cl/7306078
- Go言語の公式ドキュメント (pkg.go.dev)
- Go言語のブログ記事 (go.dev/blog)
- Go言語のテストとExample関数の一般的な知識