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

[インデックス 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 パッケージの機能を示します。

  1. リストの初期化: l := list.New() を呼び出して、新しい空の双方向連結リストを作成します。
  2. 要素の追加:
    • 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] のようになります。
  3. リストの走査: for e := l.Front(); e != nil; e = e.Next() { ... } ループを使用して、リストの先頭から末尾までを走査します。
    • l.Front(): リストの最初の要素を取得します。
    • e != nil: 現在の要素が nil でない限りループを続けます(リストの末尾に達するまで)。
    • e = e.Next(): 次のイテレーションのために、現在の要素を次の要素に進めます。
    • fmt.Println(e.Value): 各要素の Value フィールド(interface{} 型)を標準出力に出力します。
  4. 期待される出力の指定: // 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 パッケージの基本的な使用例を簡潔に示しています。

  1. パッケージ宣言とインポート:

    • package list_test: このファイルが list パッケージの外部テストであることを示します。
    • import ("container/list", "fmt"): container/list パッケージと、標準出力を行うための fmt パッケージをインポートしています。
  2. 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.Valueinterface{} 型なので、fmt.Println がその値を適切に表示します。
    • // Output: ブロック: このコメントブロックは、go test がこの Example 関数の出力を検証するために使用します。この例では、1, 2, 3, 4 がそれぞれ新しい行に出力されることを期待しています。

このコードは、container/list パッケージの主要なAPIを効果的にデモンストレーションしており、Go言語の Example 関数の慣習に従って、ドキュメントとテストの両方の役割を果たしています。

関連リンク

参考にした情報源リンク