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

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

このコミットは、Go言語の標準ライブラリであるlogパッケージに新しいテスト例を追加するものです。具体的には、log.Loggerの基本的な使用方法を示すExampleLogger関数がsrc/pkg/log/example_test.goファイルに追加されました。

コミット

commit 8c530becaf55ce3285121d0bf640085520ac3a4b
Author: ChaiShushan <chaishushan@gmail.com>
Date:   Wed Dec 18 16:24:11 2013 +1100

    log: add example
    
    Fixes #6028.
    
    R=golang-dev, bradfitz, adg, r
    CC=golang-dev
    https://golang.org/cl/43320043

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

https://github.com/golang/go/commit/8c530becaf55ce3285121d0bf640085520ac3a4b

元コミット内容

log: add example
Fixes #6028.
R=golang-dev, bradfitz, adg, r
CC=golang-dev
https://golang.org/cl/43320043

変更の背景

このコミットは、Go言語のIssue 6028「logパッケージに例を追加する」に対応するものです。Go言語の標準ライブラリは、その機能の理解と適切な使用を促進するために、豊富なドキュメントとコード例を提供することが推奨されています。特に、logパッケージのような基本的なユーティリティは、開発者がログ出力のベストプラクティスを学ぶ上で、具体的なコード例が非常に役立ちます。

このコミット以前は、logパッケージのドキュメントには、log.New関数を使用してカスタムロガーを作成し、その出力先やフォーマットを制御する方法を示す具体的な例が不足していた可能性があります。そのため、開発者がlogパッケージの柔軟性を十分に活用するためには、より実践的なコード例が必要とされていました。このコミットは、そのギャップを埋め、logパッケージの利用方法をより明確にすることを目的としています。

前提知識の解説

Go言語のlogパッケージ

Go言語の標準ライブラリには、基本的なロギング機能を提供するlogパッケージが含まれています。このパッケージは、アプリケーションのイベント、エラー、デバッグ情報などを標準出力、ファイル、またはその他のI/Oライターに出力するために使用されます。

  • デフォルトロガー: logパッケージは、log.Print, log.Printf, log.Println, log.Fatal, log.Fatalf, log.Fatalln, log.Panic, log.Panicf, log.Paniclnなどの関数を通じて、すぐに使用できるデフォルトロガーを提供します。これらは通常、標準エラー出力にログを出力します。
  • カスタムロガー: log.New関数を使用することで、開発者は独自のロガーインスタンスを作成できます。これにより、ログの出力先(io.Writerインターフェースを実装する任意の型)、ログメッセージのプレフィックス、およびログフラグ(タイムスタンプ、ファイル名、行番号など)を細かく制御できます。

io.Writerインターフェース

Go言語のioパッケージは、I/O操作のための基本的なインターフェースを定義しています。io.Writerインターフェースは、データを書き込むための単一のWriteメソッドを持つインターフェースです。

type Writer interface {
    Write(p []byte) (n int, err error)
}

log.New関数は、このio.Writerインターフェースを実装する任意のオブジェクトをログの出力先として受け取ります。これにより、ログを標準出力、ファイル、ネットワーク接続、またはメモリ上のバッファなど、様々な場所に柔軟に出力することが可能になります。

bytes.Buffer

bytesパッケージのBuffer型は、可変長のバイトバッファを実装しており、io.Writerインターフェースを満たします。これは、データをメモリ上に一時的に蓄積するために非常に便利です。テストコードでは、ログ出力をファイルや標準出力に直接書き出す代わりに、bytes.Bufferに書き出すことで、その内容をプログラム内で簡単に検証できるようになります。

logパッケージのフラグ

logパッケージは、ログメッセージに含める追加情報を制御するための様々なフラグを提供します。これらはビットマスクとして定義されており、log.New関数やlog.SetFlags関数に渡すことで設定できます。

  • log.Ldate: ローカルタイムゾーンでの日付(例: 2009/01/23)
  • log.Ltime: ローカルタイムゾーンでの時刻(例: 01:23:23)
  • log.Lmicroseconds: 時刻にマイクロ秒の分解能を追加(例: 01:23:23.123123)
  • log.Llongfile: 完全なファイル名と行番号(例: /a/b/c/d.go:23)
  • log.Lshortfile: 最後のパス要素と行番号(例: d.go:23)。ログメッセージの生成元を特定するのに便利です。
  • log.LUTC: 日付と時刻をUTCで表示
  • log.LstdFlags: LdateLtimeの組み合わせ

このコミットでは、log.Lshortfileフラグが使用されており、ログメッセージにファイル名と行番号が含まれるようになります。

Go言語のテストとExample関数

Go言語のテストフレームワークは、_test.goファイルに記述されたテスト関数を自動的に発見し実行します。Goのテストには、ユニットテスト、ベンチマークテスト、そしてExampleテストの3種類があります。

  • Exampleテスト: Example関数は、コードの動作例を示すために使用されます。これらの関数は、通常のテスト関数と同様にgo testコマンドによって実行されますが、その目的はコードの動作を検証することよりも、ドキュメントとして機能することにあります。Example関数の特別な機能として、関数内のコメントに// Output:というプレフィックスを付けて期待される出力を記述することができます。go testは、実際に実行された関数の出力とこの// Output:コメントの内容を比較し、一致しない場合はテストを失敗させます。これにより、コード例が常に最新かつ正確であることを保証できます。また、go docコマンドでパッケージのドキュメントを生成する際に、Example関数の内容が自動的にドキュメントに組み込まれるため、非常に効果的なドキュメンテーションツールとなります。

技術的詳細

このコミットは、logパッケージのExampleLogger関数をsrc/pkg/log/example_test.goという新しいファイルに追加します。このファイルは、Goのテスト規約に従い、log_testパッケージに属しています。これは、テスト対象のパッケージ(log)とは異なるパッケージにテストを配置することで、外部からパッケージを使用する際の挙動をテストする「外部テスト」の形式を取っていることを意味します。

ExampleLogger関数は、以下のステップでlog.Loggerの基本的な使用方法を示しています。

  1. bytes.Bufferの初期化: var buf bytes.Bufferによって、ログメッセージを書き込むためのメモリ上のバッファが作成されます。これにより、ログ出力を標準出力に直接書き出すことなく、プログラム内でその内容をキャプチャし、検証することが可能になります。
  2. log.Newによるロガーの作成: logger := log.New(&buf, "logger: ", log.Lshortfile)という行で、新しいlog.Loggerインスタンスが作成されます。
    • 第一引数&bufは、ログの出力先として先ほど作成したbytes.Bufferのアドレスを渡しています。
    • 第二引数"logger: "は、各ログメッセージの前に付加されるプレフィックスです。
    • 第三引数log.Lshortfileは、ログメッセージにログを呼び出したソースファイル名と行番号を含めるためのフラグです。
  3. ログメッセージの出力: logger.Print("Hello, log file!")によって、作成したロガーインスタンスを使用してログメッセージが出力されます。このメッセージはbufに書き込まれます。
  4. バッファの内容の出力: fmt.Print(&buf)によって、bufに蓄積されたログメッセージが標準出力に書き出されます。これは、Exampleテストの// Output:コメントと比較するために必要です。
  5. 期待される出力の定義: // Output:コメントブロックは、このExample関数が実行されたときに期待される正確な出力を定義しています。
    • logger: example_test.go:15: Hello, log file!
    • この出力は、設定されたプレフィックス(logger: )、ファイル名と行番号(example_test.go:15:)、そして実際のログメッセージ(Hello, log file!)が結合されたものです。行番号15は、logger.Printが呼び出されたexample_test.go内の行番号に対応します。

このExample関数は、go test実行時に自動的にテストされ、その出力が// Output:コメントと一致することが検証されます。これにより、log.Newの基本的な挙動と、log.Lshortfileフラグの効果が明確に示され、ドキュメントとしても機能します。

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

src/pkg/log/example_test.goという新しいファイルが追加され、以下の内容が記述されています。

--- /dev/null
+++ b/src/pkg/log/example_test.go
@@ -0,0 +1,21 @@
+// 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 log_test
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+)
+
+func ExampleLogger() {
+	var buf bytes.Buffer
+	logger := log.New(&buf, "logger: ", log.Lshortfile)
+	logger.Print("Hello, log file!")
+
+	fmt.Print(&buf)
+	// Output:
+	// logger: example_test.go:15: Hello, log file!
+}

コアとなるコードの解説

追加されたExampleLogger関数は、logパッケージのカスタムロガーの作成と使用方法を簡潔に示しています。

  1. package log_test: この行は、このファイルがlogパッケージの外部テストであることを示します。これにより、logパッケージの公開されたAPIのみがテストされ、パッケージの内部実装に依存しないテストが保証されます。
  2. importブロック:
    • "bytes": bytes.Bufferを使用するためにインポートされます。
    • "fmt": fmt.Printを使用してバッファの内容を標準出力に書き出すためにインポートされます。
    • "log": テスト対象のlogパッケージ自体をインポートします。
  3. func ExampleLogger(): この関数は、Goのテストフレームワークによって特別なExampleテストとして認識されます。
  4. var buf bytes.Buffer: ログメッセージをキャプチャするためのbytes.Bufferインスタンスを宣言します。
  5. logger := log.New(&buf, "logger: ", log.Lshortfile):
    • log.Newを呼び出して新しいロガーを作成します。
    • &buf: ログの出力先としてbufのアドレスを渡します。これにより、logger.Printが呼び出されたときに、メッセージはbufに書き込まれます。
    • "logger: ": ログメッセージのプレフィックスを設定します。
    • log.Lshortfile: ログメッセージに、ログ呼び出し元のファイル名と行番号(例: example_test.go:15:)を含めるように設定します。
  6. logger.Print("Hello, log file!"): 作成したロガーを使用して、指定された文字列をログに出力します。この出力はbufに格納されます。
  7. fmt.Print(&buf): bufに蓄積されたすべての内容を標準出力に書き出します。これは、Exampleテストの// Output:コメントとの比較のために必要です。
  8. // Output:コメント: この特別なコメントは、ExampleLogger関数が実行されたときに期待される正確な出力を定義します。go testコマンドは、実際の出力とこのコメントの内容を比較し、一致しない場合はテストを失敗させます。これにより、コード例が常に正しく、ドキュメントとして機能することが保証されます。

このコードは、log.Newの柔軟性、特にカスタム出力先とフラグの設定能力を明確に示しており、logパッケージのドキュメントを補完する重要な役割を果たします。

関連リンク

参考にした情報源リンク

このコミットは、Go言語の標準ライブラリであるlogパッケージに新しいテスト例を追加するものです。具体的には、log.Loggerの基本的な使用方法を示すExampleLogger関数がsrc/pkg/log/example_test.goファイルに追加されました。

コミット

commit 8c530becaf55ce3285121d0bf640085520ac3a4b
Author: ChaiShushan <chaishushan@gmail.com>
Date:   Wed Dec 18 16:24:11 2013 +1100

    log: add example
    
    Fixes #6028.
    
    R=golang-dev, bradfitz, adg, r
    CC=golang-dev
    https://golang.org/cl/43320043

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

https://github.com/golang/go/commit/8c530becaf55ce3285121d0bf640085520ac3a4b

元コミット内容

log: add example
Fixes #6028.
R=golang-dev, bradfitz, adg, r
CC=golang-dev
https://golang.org/cl/43320043

変更の背景

このコミットは、Go言語のIssue 6028「logパッケージに例を追加する」に対応するものです。Go言語の標準ライブラリは、その機能の理解と適切な使用を促進するために、豊富なドキュメントとコード例を提供することが推奨されています。特に、logパッケージのような基本的なユーティリティは、開発者がログ出力のベストプラクティスを学ぶ上で、具体的なコード例が非常に役立ちます。

このコミット以前は、logパッケージのドキュメントには、log.New関数を使用してカスタムロガーを作成し、その出力先やフォーマットを制御する方法を示す具体的な例が不足していた可能性があります。そのため、開発者がlogパッケージの柔軟性を十分に活用するためには、より実践的なコード例が必要とされていました。このコミットは、そのギャップを埋め、logパッケージの利用方法をより明確にすることを目的としています。

前提知識の解説

Go言語のlogパッケージ

Go言語の標準ライブラリには、基本的なロギング機能を提供するlogパッケージが含まれています。このパッケージは、アプリケーションのイベント、エラー、デバッグ情報などを標準出力、ファイル、またはその他のI/Oライターに出力するために使用されます。

  • デフォルトロガー: logパッケージは、log.Print, log.Printf, log.Println, log.Fatal, log.Fatalf, log.Fatalln, log.Panic, log.Panicf, log.Paniclnなどの関数を通じて、すぐに使用できるデフォルトロガーを提供します。これらは通常、標準エラー出力にログを出力します。
  • カスタムロガー: log.New関数を使用することで、開発者は独自のロガーインスタンスを作成できます。これにより、ログの出力先(io.Writerインターフェースを実装する任意の型)、ログメッセージのプレフィックス、およびログフラグ(タイムスタンプ、ファイル名、行番号など)を細かく制御できます。

io.Writerインターフェース

Go言語のioパッケージは、I/O操作のための基本的なインターフェースを定義しています。io.Writerインターフェースは、データを書き込むための単一のWriteメソッドを持つインターフェースです。

type Writer interface {
    Write(p []byte) (n int, err error)
}

log.New関数は、このio.Writerインターフェースを実装する任意のオブジェクトをログの出力先として受け取ります。これにより、ログを標準出力、ファイル、ネットワーク接続、またはメモリ上のバッファなど、様々な場所に柔軟に出力することが可能になります。

bytes.Buffer

bytesパッケージのBuffer型は、可変長のバイトバッファを実装しており、io.Writerインターフェースを満たします。これは、データをメモリ上に一時的に蓄積するために非常に便利です。テストコードでは、ログ出力をファイルや標準出力に直接書き出す代わりに、bytes.Bufferに書き出すことで、その内容をプログラム内で簡単に検証できるようになります。

logパッケージのフラグ

logパッケージは、ログメッセージに含める追加情報を制御するための様々なフラグを提供します。これらはビットマスクとして定義されており、log.New関数やlog.SetFlags関数に渡すことで設定できます。

  • log.Ldate: ローカルタイムゾーンでの日付(例: 2009/01/23)
  • log.Ltime: ローカルタイムゾーンでの時刻(例: 01:23:23)
  • log.Lmicroseconds: 時刻にマイクロ秒の分解能を追加(例: 01:23:23.123123)
  • log.Llongfile: 完全なファイル名と行番号(例: /a/b/c/d.go:23)
  • log.Lshortfile: 最後のパス要素と行番号(例: d.go:23)。ログメッセージの生成元を特定するのに便利です。
  • log.LUTC: 日付と時刻をUTCで表示
  • log.LstdFlags: LdateLtimeの組み合わせ

このコミットでは、log.Lshortfileフラグが使用されており、ログメッセージにファイル名と行番号が含まれるようになります。

Go言語のテストとExample関数

Go言語のテストフレームワークは、_test.goファイルに記述されたテスト関数を自動的に発見し実行します。Goのテストには、ユニットテスト、ベンチマークテスト、そしてExampleテストの3種類があります。

  • Exampleテスト: Example関数は、コードの動作例を示すために使用されます。これらの関数は、通常のテスト関数と同様にgo testコマンドによって実行されますが、その目的はコードの動作を検証することよりも、ドキュメントとして機能することにあります。Example関数の特別な機能として、関数内のコメントに// Output:というプレフィックスを付けて期待される出力を記述することができます。go testは、実際に実行された関数の出力とこの// Output:コメントの内容を比較し、一致しない場合はテストを失敗させます。これにより、コード例が常に最新かつ正確であることを保証できます。また、go docコマンドでパッケージのドキュメントを生成する際に、Example関数の内容が自動的にドキュメントに組み込まれるため、非常に効果的なドキュメンテーションツールとなります。

技術的詳細

このコミットは、logパッケージのExampleLogger関数をsrc/pkg/log/example_test.goという新しいファイルに追加します。このファイルは、Goのテスト規約に従い、log_testパッケージに属しています。これは、テスト対象のパッケージ(log)とは異なるパッケージにテストを配置することで、外部からパッケージを使用する際の挙動をテストする「外部テスト」の形式を取っていることを意味します。

ExampleLogger関数は、以下のステップでlog.Loggerの基本的な使用方法を示しています。

  1. bytes.Bufferの初期化: var buf bytes.Bufferによって、ログメッセージを書き込むためのメモリ上のバッファが作成されます。これにより、ログ出力を標準出力に直接書き出すことなく、プログラム内でその内容をキャプチャし、検証することが可能になります。
  2. log.Newによるロガーの作成: logger := log.New(&buf, "logger: ", log.Lshortfile)という行で、新しいlog.Loggerインスタンスが作成されます。
    • 第一引数&bufは、ログの出力先として先ほど作成したbytes.Bufferのアドレスを渡しています。
    • 第二引数"logger: "は、各ログメッセージの前に付加されるプレフィックスです。
    • 第三引数log.Lshortfileは、ログメッセージにログを呼び出したソースファイル名と行番号を含めるためのフラグです。
  3. ログメッセージの出力: logger.Print("Hello, log file!")によって、作成したロガーインスタンスを使用してログメッセージが出力されます。このメッセージはbufに書き込まれます。
  4. バッファの内容の出力: fmt.Print(&buf)によって、bufに蓄積されたログメッセージが標準出力に書き出されます。これは、Exampleテストの// Output:コメントと比較するために必要です。
  5. 期待される出力の定義: // Output:コメントブロックは、このExample関数が実行されたときに期待される正確な出力を定義しています。
    • logger: example_test.go:15: Hello, log file!
    • この出力は、設定されたプレフィックス(logger: )、ファイル名と行番号(example_test.go:15:)、そして実際のログメッセージ(Hello, log file!)が結合されたものです。行番号15は、logger.Printが呼び出されたexample_test.go内の行番号に対応します。

このExample関数は、go test実行時に自動的にテストされ、その出力が// Output:コメントと一致することが検証されます。これにより、log.Newの基本的な挙動と、log.Lshortfileフラグの効果が明確に示され、ドキュメントとしても機能します。

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

src/pkg/log/example_test.goという新しいファイルが追加され、以下の内容が記述されています。

--- /dev/null
+++ b/src/pkg/log/example_test.go
@@ -0,0 +1,21 @@
+// 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 log_test
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+)
+
+func ExampleLogger() {
+	var buf bytes.Buffer
+	logger := log.New(&buf, "logger: ", log.Lshortfile)
+	logger.Print("Hello, log file!")
+
+	fmt.Print(&buf)
+	// Output:
+	// logger: example_test.go:15: Hello, log file!
+}

コアとなるコードの解説

追加されたExampleLogger関数は、logパッケージのカスタムロガーの作成と使用方法を簡潔に示しています。

  1. package log_test: この行は、このファイルがlogパッケージの外部テストであることを示します。これにより、logパッケージの公開されたAPIのみがテストされ、パッケージの内部実装に依存しないテストが保証されます。
  2. importブロック:
    • "bytes": bytes.Bufferを使用するためにインポートされます。
    • "fmt": fmt.Printを使用してバッファの内容を標準出力に書き出すためにインポートされます。
    • "log": テスト対象のlogパッケージ自体をインポートします。
  3. func ExampleLogger(): この関数は、Goのテストフレームワークによって特別なExampleテストとして認識されます。
  4. var buf bytes.Buffer: ログメッセージをキャプチャするためのbytes.Bufferインスタンスを宣言します。
  5. logger := log.New(&buf, "logger: ", log.Lshortfile):
    • log.Newを呼び出して新しいロガーを作成します。
    • &buf: ログの出力先としてbufのアドレスを渡します。これにより、logger.Printが呼び出されたときに、メッセージはbufに書き込まれます。
    • "logger: ": ログメッセージのプレフィックスを設定します。
    • log.Lshortfile: ログメッセージに、ログ呼び出し元のファイル名と行番号(例: example_test.go:15:)を含めるように設定します。
  6. logger.Print("Hello, log file!"): 作成したロガーを使用して、指定された文字列をログに出力します。この出力はbufに格納されます。
  7. fmt.Print(&buf): bufに蓄積されたすべての内容を標準出力に書き出します。これは、Exampleテストの// Output:コメントとの比較のために必要です。
  8. // Output:コメント: この特別なコメントは、ExampleLogger関数が実行されたときに期待される正確な出力を定義します。go testコマンドは、実際の出力とこのコメントの内容を比較し、一致しない場合はテストを失敗させます。これにより、コード例が常に正しく、ドキュメントとして機能することが保証されます。

このコードは、log.Newの柔軟性、特にカスタム出力先とフラグの設定能力を明確に示しており、logパッケージのドキュメントを補完する重要な役割を果たします。

関連リンク

参考にした情報源リンク