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

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

このコミットは、Go言語の標準ライブラリである compress/zlib パッケージに対する軽微な修正と、使用例の追加を行っています。具体的には、src/pkg/compress/zlib/example_test.go という新しいファイルが追加され、zlib.NewWriterzlib.NewReader の使用方法を示す実行可能な例が提供されています。また、src/pkg/compress/zlib/reader.go では、zlib.NewWriter の呼び出しにおける不要なエラー変数 err の削除という小さな修正が行われています。

コミット

  • コミットハッシュ: dd963ddf05ff84db489bf462c8ad500b84e72dcb
  • 作者: Quan Yong Zhai qyzhai@gmail.com
  • コミット日時: 2012年4月21日 土曜日 14:34:42 +1000

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

https://github.com/golang/go/commit/dd963ddf05ff84db489bf462c8ad500b84e72dcb

元コミット内容

compress/zlib: minor fixes

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/6058043

変更の背景

このコミットの背景には、Go言語の標準ライブラリの品質向上と、ユーザーがライブラリをより簡単に利用できるようにするための努力があります。

  1. reader.go の修正: zlib.NewWriter 関数は、Go 1.0のリリース時点ではエラーを返さない設計になっていました。しかし、以前のコードでは w, err := zlib.NewWriter(&b) のようにエラー変数を宣言していましたが、これは不要であり、静的解析ツールやコンパイラによって「宣言されたが使用されていない変数」として警告される可能性がありました。このコミットは、このような冗長なコードを削除し、コードの簡潔性と正確性を向上させることを目的としています。これは「minor fixes」(軽微な修正)の一部と見なされます。

  2. example_test.go の追加: Go言語では、_test.go ファイル内に Example 関数を記述することで、パッケージの使用例をドキュメントとして提供し、かつテストとして実行できる仕組みがあります。これにより、ドキュメントの正確性が保証され、ユーザーは実際のコードスニペットを通じてライブラリの利用方法を学ぶことができます。compress/zlib パッケージは圧縮・解凍という重要な機能を提供するため、その基本的な使用方法を示す具体的な例は、ユーザーの理解を深め、誤用を防ぐ上で非常に有用です。このコミットは、zlib.NewWriterzlib.NewReader の基本的な圧縮・解凍フローを示す例を追加することで、パッケージの使いやすさを向上させています。

前提知識の解説

Zlib (zlib)

Zlibは、データ圧縮のためのオープンソースのソフトウェアライブラリです。RFC 1950 (Zlib), RFC 1951 (Deflate), RFC 1952 (Gzip) で定義されているDeflate圧縮アルゴリズムを実装しています。Deflateは、LZ77アルゴリズムとハフマン符号化を組み合わせたロスレスデータ圧縮アルゴリズムです。Zlibは、多くのオペレーティングシステム、ファイル形式、ネットワークプロトコルで広く使用されています。

Go言語の compress/zlib パッケージ

Go言語の標準ライブラリには、Zlib形式のデータ圧縮・解凍を扱う compress/zlib パッケージが含まれています。このパッケージは、io.Reader および io.Writer インターフェースと連携するように設計されており、ストリームベースの圧縮・解凍を容易に行うことができます。

  • zlib.NewWriter(w io.Writer) *zlib.Writer: 指定された io.Writer にZlib形式で圧縮されたデータを書き込む新しい zlib.Writer を作成します。
  • zlib.NewReader(r io.Reader) (io.ReadCloser, error): 指定された io.Reader からZlib形式で圧縮されたデータを読み込む新しい io.ReadCloser を作成します。この関数は、入力データが有効なZlib形式でない場合にエラーを返す可能性があります。

Go言語の Example テスト

Go言語のテストフレームワークは、単体テスト (TestXxx)、ベンチマークテスト (BenchmarkXxx) に加えて、ExampleXxx 関数をサポートしています。

  • ExampleXxx 関数は、パッケージのドキュメントに表示されるコード例として機能します。
  • これらの例は go test コマンドによって実際に実行され、出力がコメント内の // Output: と一致するかどうかが検証されます。これにより、ドキュメントのコード例が常に最新かつ正確であることが保証されます。
  • Example 関数は、パッケージの公開APIの利用方法をユーザーに示すための非常に効果的な手段です。

技術的詳細

src/pkg/compress/zlib/example_test.go の追加

このファイルは、compress/zlib パッケージの基本的な使用例を提供します。

  • ExampleNewWriter():

    • bytes.Buffer を出力先として使用し、zlib.NewWriter を初期化します。
    • w.Write([]byte("hello, world\\n")) でデータを書き込みます。
    • w.Close() を呼び出すことで、バッファリングされたデータをフラッシュし、Zlibストリームを適切に終了させます。
    • fmt.Println(b.Bytes()) で圧縮されたバイト列を出力します。// Output: コメントにより、期待される圧縮バイト列が明示されています。
  • ExampleNewReader():

    • ExampleNewWriter() で生成されたものと同じZlib圧縮バイト列を bytes.Buffer に格納します。
    • zlib.NewReader を使用して、このバッファから読み込むリーダーを初期化します。
    • エラーハンドリング (if err != nil { panic(err) }) が含まれています。NewReader は入力が不正な場合にエラーを返す可能性があるため、これは重要です。
    • io.Copy(os.Stdout, r) を使用して、解凍されたデータを標準出力に直接コピーします。
    • // Output: hello, world コメントにより、期待される解凍後の文字列が明示されています。
    • r.Close() を呼び出すことで、リーダーを適切にクローズします。

これらの例は、Goの io パッケージのインターフェース (io.Writer, io.Reader, io.Closer) と compress/zlib パッケージがどのように連携して動作するかを明確に示しています。

src/pkg/compress/zlib/reader.go の修正

この修正は非常に小さいですが、コードの品質と一貫性を向上させます。

  • 変更前: w, err := zlib.NewWriter(&b)
  • 変更後: w := zlib.NewWriter(&b)

zlib.NewWriter 関数は、Go 1.0の設計ではエラーを返しません。したがって、err 変数を宣言してその戻り値を受け取ることは不要であり、Goのコンパイラやリンターによっては「宣言されたが使用されていない変数」として警告される可能性があります。この修正は、この冗長な err 変数の宣言を削除し、コードをより簡潔でGoのイディオムに沿ったものにしています。

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

diff --git a/src/pkg/compress/zlib/example_test.go b/src/pkg/compress/zlib/example_test.go
new file mode 100644
index 0000000000..b934ffa618
--- /dev/null
+++ b/src/pkg/compress/zlib/example_test.go
@@ -0,0 +1,37 @@
+// Copyright 2012 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 zlib_test
+
+import (
+	"bytes"
+	"compress/zlib"
+	"fmt"
+	"io"
+	"os"
+)
+
+func ExampleNewWriter() {
+	var b bytes.Buffer
+
+	w := zlib.NewWriter(&b)
+	w.Write([]byte("hello, world\n"))
+	w.Close()
+	fmt.Println(b.Bytes())
+	// Output: [120 156 202 72 205 201 201 215 81 40 207 47 202 73 225 2 4 0 0 255 255 33 231 4 147]
+}
+
+func ExampleNewReader() {
+	buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
+	b := bytes.NewBuffer(buff)
+
+	r, err := zlib.NewReader(b)
+	if err != nil {
+		panic(err)
+	}
+	io.Copy(os.Stdout, r)
+	// Output: hello, world
+	r.Close()
+}
diff --git a/src/pkg/compress/zlib/reader.go b/src/pkg/compress/zlib/reader.go
index f38ef5a885..d54746f4c0 100644
--- a/src/pkg/compress/zlib/reader.go
+++ b/src/pkg/compress/zlib/reader.go
@@ -11,7 +11,7 @@ and compress during writing.  For example, to write compressed data
 to a buffer:
 
 	var b bytes.Buffer
-	w, err := zlib.NewWriter(&b)
+	w := zlib.NewWriter(&b)
 	w.Write([]byte("hello, world\n"))
 	w.Close()
 

コアとなるコードの解説

src/pkg/compress/zlib/example_test.go

このファイルは完全に新規追加されたもので、compress/zlib パッケージの基本的な圧縮・解凍のワークフローを実演しています。

  • パッケージ宣言: package zlib_test となっており、これは zlib パッケージの外部からテストを行うことを意味します。これにより、公開されたAPIのみを使用して例が記述されていることが保証されます。
  • インポート: bytes, compress/zlib, fmt, io, os といった標準ライブラリがインポートされています。これらは、バッファ操作、Zlib圧縮・解凍、出力フォーマット、I/O操作、標準出力への書き込みにそれぞれ必要です。
  • ExampleNewWriter() 関数:
    • var b bytes.Buffer で、圧縮されたデータが書き込まれるメモリバッファを宣言します。
    • w := zlib.NewWriter(&b) で、bytes.Buffer をラップする zlib.Writer を作成します。この zlib.Writer は、io.Writer インターフェースを実装しており、書き込まれたデータをZlib形式で圧縮して内部の bytes.Buffer に出力します。
    • w.Write([]byte("hello, world\\n")) で、圧縮したい元のデータを zlib.Writer に書き込みます。
    • w.Close() は非常に重要です。Zlib圧縮はストリームベースであり、Close を呼び出すことで、内部バッファに残っているデータをフラッシュし、Zlibストリームのフッター(チェックサムなど)を書き込みます。これを忘れると、圧縮されたデータが不完全になり、解凍時にエラーが発生する可能性があります。
    • fmt.Println(b.Bytes()) で、圧縮されたバイト列をそのまま出力します。// Output: コメントは、go test 実行時にこの出力と一致するかどうかを検証するために使用されます。
  • ExampleNewReader() 関数:
    • buff := []byte{...} で、ExampleNewWriter() で得られたZlib圧縮バイト列を直接定義しています。これは、テストの独立性を保ちつつ、圧縮されたデータの例を提供するためです。
    • b := bytes.NewBuffer(buff) で、このバイト列を読み込むための bytes.Buffer を作成します。
    • r, err := zlib.NewReader(b) で、bytes.Buffer をラップする zlib.Reader を作成します。この zlib.Reader は、io.Reader インターフェースを実装しており、内部の bytes.Buffer からZlib圧縮データを読み込み、解凍して提供します。NewReader は、入力データが有効なZlib形式でない場合にエラーを返す可能性があるため、エラーハンドリングが必要です。
    • if err != nil { panic(err) } は、エラーが発生した場合にプログラムを終了させる簡単なエラーハンドリングです。実際のアプリケーションでは、より堅牢なエラー処理が求められます。
    • io.Copy(os.Stdout, r) は、zlib.Reader から読み込んだ解凍済みデータを os.Stdout (標準出力) に直接コピーします。これは、ストリーム処理の典型的なパターンです。
    • // Output: hello, world コメントは、解凍されたデータが元の文字列と一致するかどうかを検証するために使用されます。
    • r.Close() は、zlib.Reader が内部で使用するリソースを解放するために重要です。

src/pkg/compress/zlib/reader.go

このファイルでは、既存のコメントブロック内のコードスニペットが修正されています。

  • 変更点: w, err := zlib.NewWriter(&b) から w := zlib.NewWriter(&b) への変更。
  • 理由: zlib.NewWriter 関数は、Go 1.0の設計ではエラーを返しません。したがって、err 変数を宣言してその戻り値を受け取ることは不要であり、Goのコンパイラやリンターによっては「宣言されたが使用されていない変数」として警告される可能性があります。この修正は、この冗長な err 変数の宣言を削除し、コードをより簡潔でGoのイディオムに沿ったものにすることで、コメント内のコードスニペットが実際のAPIの振る舞いを正確に反映するようにしています。これは、ドキュメントの正確性を保つための「minor fix」です。

関連リンク

参考にした情報源リンク