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

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

このコミットは、Go言語の標準ライブラリ encoding/binary パッケージの ExampleRead 関数におけるサンプルコードの変更に関するものです。具体的には、バイナリデータを読み込む際の入力元として bytes.Buffer の代わりに bytes.Reader を使用するように修正されています。これは、読み込み操作においてより適切で効率的な Reader インターフェースの実装を利用するための改善です。

コミット

commit d5c806d581f4d110dfc2696c8b18b4ecde82e453
Author: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Date:   Tue Aug 27 06:32:24 2013 -0700

    encoding/binary: use bytes.Reader in read example
    
    R=golang-dev, dave
    CC=golang-dev
    https://golang.org/cl/13274043

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

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

元コミット内容

encoding/binary: use bytes.Reader in read example

このコミットは、encoding/binary パッケージの読み込み例において、bytes.Reader を使用するように変更するものです。

変更の背景

Go言語の io パッケージには、データの読み書きのための基本的なインターフェースが定義されています。io.Reader はデータの読み込み操作を抽象化し、io.Writer はデータの書き込み操作を抽象化します。

bytes.Buffer は、可変長のバイトバッファを実装しており、io.Readerio.Writer の両方のインターフェースを満たします。そのため、データの読み書きの両方に使用できます。一方、bytes.Reader は、既存のバイトスライスからデータを読み込むための io.Reader の実装であり、書き込み操作はサポートしていません。

encoding/binary.Read 関数は、io.Reader インターフェースを引数として受け取り、バイナリデータを読み込みます。このコミットが行われる前は、ExampleRead 関数内で bytes.Buffer を使用してバイトスライスからデータを読み込んでいました。しかし、この例の目的は「読み込み」であり、bytes.Buffer が提供する書き込み機能は不要でした。

この変更の背景には、コードの意図をより明確にし、適切なツールを適切な目的で使用するというGo言語の設計思想があります。bytes.Reader は読み込み専用の操作に特化しており、bytes.Buffer よりも読み込み操作の意図を明確に伝えます。また、bytes.Reader は内部的にバイトスライスへの参照を持つため、bytes.Buffer のように内部バッファを動的に拡張する必要がなく、読み込み操作においてはより効率的である可能性があります。

前提知識の解説

encoding/binary パッケージ

encoding/binary パッケージは、Goのデータ構造とバイトシーケンスの間で変換を行うための関数を提供します。特に、数値型(int, float など)や構造体を、リトルエンディアンまたはビッグエンディアンのバイト列として読み書きする際に使用されます。

  • binary.Read(r io.Reader, order ByteOrder, data interface{}) error: r からバイナリデータを読み込み、data に格納します。order はバイトオーダー(binary.LittleEndian または binary.BigEndian)を指定します。data はポインタである必要があります。
  • binary.Write(w io.Writer, order ByteOrder, data interface{}) error: data をバイナリデータとして w に書き込みます。

bytes パッケージ

bytes パッケージは、バイトスライスの操作に役立つ関数を提供します。このコミットに関連するのは以下の2つの型です。

  • bytes.Buffer: 可変長のバイトバッファです。io.Readerio.Writerio.ByteScannerio.RuneScanner インターフェースを実装しており、データの読み書きの両方に使用できます。NewBuffer(buf []byte) で初期化すると、buf の内容を初期データとして持ち、その後の書き込みはバッファの末尾に追加されます。
  • bytes.Reader: 既存のバイトスライスからデータを読み込むための io.Reader の実装です。NewReader(b []byte) で初期化され、b の内容を読み込みます。io.Readerio.ReaderAtio.Seekerio.ByteScannerio.RuneScanner インターフェースを実装しています。書き込み操作はサポートしていません。

io パッケージのインターフェース

  • io.Reader: Read(p []byte) (n int, err error) メソッドを持つインターフェース。データを読み込むための基本的なインターフェースです。
  • io.Writer: Write(p []byte) (n int, err error) メソッドを持つインターフェース。データを書き込むための基本的なインターフェースです。

技術的詳細

この変更は、encoding/binary パッケージの ExampleRead 関数において、バイナリデータの読み込み元として bytes.Buffer の代わりに bytes.Reader を使用するように修正したものです。

元のコードでは、bytes.NewBuffer(b) を使用して bytes.Buffer を作成し、それを binary.Read に渡していました。bytes.Bufferio.Reader インターフェースを満たすため、これは機能的には問題ありませんでした。

// 変更前
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
buf := bytes.NewBuffer(b) // bytes.Buffer を使用
err := binary.Read(buf, binary.LittleEndian, &pi)

しかし、この例の目的はバイトスライス b からデータを「読み込む」ことのみであり、bytes.Buffer が持つ「書き込み」機能は不要です。bytes.Reader は、既存のバイトスライスから読み込むことに特化した io.Reader の実装であり、このユースケースにより適しています。

// 変更後
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
buf := bytes.NewReader(b) // bytes.Reader を使用
err := binary.Read(buf, binary.LittleEndian, &pi)

この変更により、以下の利点があります。

  1. 意図の明確化: コードを読む人に対して、この操作が読み込み専用であることをより明確に伝えます。bytes.Reader を使用することで、開発者はこのデータソースが変更されない(書き込まれない)ことをすぐに理解できます。
  2. 適切な抽象化の利用: bytes.Readerio.Reader インターフェースを実装しており、binary.Read が期待するインターフェースに完全に合致します。不要な機能(書き込み)を持つ bytes.Buffer を使うよりも、より特化した bytes.Reader を使う方が、設計上も優れています。
  3. 潜在的な効率性: bytes.Reader は内部的に元のバイトスライスへの参照を持つため、bytes.Buffer のように内部バッファを動的に管理する必要がありません。これにより、特に大きなデータセットを扱う場合や、頻繁に読み込み操作が行われる場合に、わずかながらパフォーマンス上の利点がある可能性があります。ただし、この例のような小さなデータでは、その差はほとんど無視できるレベルです。

この変更は、機能的なバグ修正ではなく、コードの可読性、意図の明確化、およびGo言語のイディオムに沿った改善と見なされます。

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

変更は src/pkg/encoding/binary/example_test.go ファイルの1箇所のみです。

--- a/src/pkg/encoding/binary/example_test.go
+++ b/src/pkg/encoding/binary/example_test.go
@@ -42,7 +42,7 @@ func ExampleWrite_multi() {
 func ExampleRead() {
 	var pi float64
 	b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
-	buf := bytes.NewBuffer(b)
+	buf := bytes.NewReader(b)
 	err := binary.Read(buf, binary.LittleEndian, &pi)
 	if err != nil {
 		fmt.Println("binary.Read failed:", err)

コアとなるコードの解説

変更された行は以下の通りです。

  • 変更前: buf := bytes.NewBuffer(b)
    • バイトスライス b を初期データとして持つ bytes.Buffer の新しいインスタンスを作成し、buf 変数に代入しています。
  • 変更後: buf := bytes.NewReader(b)
    • バイトスライス b からデータを読み込むための bytes.Reader の新しいインスタンスを作成し、buf 変数に代入しています。

この変更により、binary.Read 関数に渡される io.Reader の具体的な実装が bytes.Buffer から bytes.Reader に変わりました。機能的な振る舞いは同じですが、コードの意図がより明確になり、読み込み専用の操作に特化した型が使用されるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコード (特に src/pkg/encoding/binary/example_test.go および src/pkg/bytes/buffer.go, src/pkg/bytes/reader.go)
  • Go言語のコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/13274043 (これはコミットメッセージに記載されているリンクであり、変更の背景を理解する上で非常に有用です。)
  • Go言語のコミュニティにおける議論 (Stack Overflow, Go Forumなど)

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

このコミットは、Go言語の標準ライブラリ encoding/binary パッケージの ExampleRead 関数におけるサンプルコードの変更に関するものです。具体的には、バイナリデータを読み込む際の入力元として bytes.Buffer の代わりに bytes.Reader を使用するように修正されています。これは、読み込み操作においてより適切で効率的な Reader インターフェースの実装を利用するための改善です。

コミット

commit d5c806d581f4d110dfc2696c8b18b4ecde82e453
Author: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Date:   Tue Aug 27 06:32:24 2013 -0700

    encoding/binary: use bytes.Reader in read example
    
    R=golang-dev, dave
    CC=golang-dev
    https://golang.org/cl/13274043

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

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

元コミット内容

encoding/binary: use bytes.Reader in read example

このコミットは、encoding/binary パッケージの読み込み例において、bytes.Reader を使用するように変更するものです。

変更の背景

Go言語の io パッケージには、データの読み書きのための基本的なインターフェースが定義されています。io.Reader はデータの読み込み操作を抽象化し、io.Writer はデータの書き込み操作を抽象化します。

bytes.Buffer は、可変長のバイトバッファを実装しており、io.Readerio.Writer の両方のインターフェースを満たします。そのため、データの読み書きの両方に使用できます。一方、bytes.Reader は、既存のバイトスライスからデータを読み込むための io.Reader の実装であり、書き込み操作はサポートしていません。

encoding/binary.Read 関数は、io.Reader インターフェースを引数として受け取り、バイナリデータを読み込みます。このコミットが行われる前は、ExampleRead 関数内で bytes.Buffer を使用してバイトスライスからデータを読み込んでいました。しかし、この例の目的は「読み込み」であり、bytes.Buffer が提供する書き込み機能は不要でした。

この変更の背景には、コードの意図をより明確にし、適切なツールを適切な目的で使用するというGo言語の設計思想があります。bytes.Reader は読み込み専用の操作に特化しており、bytes.Buffer よりも読み込み操作の意図を明確に伝えます。また、bytes.Reader は内部的にバイトスライスへの参照を持つため、bytes.Buffer のように内部バッファを動的に拡張する必要がなく、読み込み操作においてはより効率的である可能性があります。

前提知識の解説

encoding/binary パッケージ

encoding/binary パッケージは、Goのデータ構造とバイトシーケンスの間で変換を行うための関数を提供します。特に、数値型(int, float など)や構造体を、リトルエンディアンまたはビッグエンディアンのバイト列として読み書きする際に使用されます。

  • binary.Read(r io.Reader, order ByteOrder, data interface{}) error: r からバイナリデータを読み込み、data に格納します。order はバイトオーダー(binary.LittleEndian または binary.BigEndian)を指定します。data はポインタである必要があります。
  • binary.Write(w io.Writer, order ByteOrder, data interface{}) error: data をバイナリデータとして w に書き込みます。

bytes パッケージ

bytes パッケージは、バイトスライスの操作に役立つ関数を提供します。このコミットに関連するのは以下の2つの型です。

  • bytes.Buffer: 可変長のバイトバッファです。io.Readerio.Writerio.ByteScannerio.RuneScanner インターフェースを実装しており、データの読み書きの両方に使用できます。NewBuffer(buf []byte) で初期化すると、buf の内容を初期データとして持ち、その後の書き込みはバッファの末尾に追加されます。
  • bytes.Reader: 既存のバイトスライスからデータを読み込むための io.Reader の実装です。NewReader(b []byte) で初期化され、b の内容を読み込みます。io.Readerio.ReaderAtio.Seekerio.ByteScannerio.RuneScanner インターフェースを実装しています。書き込み操作はサポートしていません。

io パッケージのインターフェース

  • io.Reader: Read(p []byte) (n int, err error) メソッドを持つインターフェース。データを読み込むための基本的なインターフェースです。
  • io.Writer: Write(p []byte) (n int, err error) メソッドを持つインターフェース。データを書き込むための基本的なインターフェースです。

技術的詳細

この変更は、encoding/binary パッケージの ExampleRead 関数において、バイナリデータの読み込み元として bytes.Buffer の代わりに bytes.Reader を使用するように修正したものです。

元のコードでは、bytes.NewBuffer(b) を使用して bytes.Buffer を作成し、それを binary.Read に渡していました。bytes.Bufferio.Reader インターフェースを満たすため、これは機能的には問題ありませんでした。

// 変更前
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
buf := bytes.NewBuffer(b) // bytes.Buffer を使用
err := binary.Read(buf, binary.LittleEndian, &pi)

しかし、この例の目的はバイトスライス b からデータを「読み込む」ことのみであり、bytes.Buffer が持つ「書き込み」機能は不要です。bytes.Reader は、既存のバイトスライスから読み込むことに特化した io.Reader の実装であり、このユースケースにより適しています。

// 変更後
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
buf := bytes.NewReader(b) // bytes.Reader を使用
err := binary.Read(buf, binary.LittleEndian, &pi)

この変更により、以下の利点があります。

  1. 意図の明確化: コードを読む人に対して、この操作が読み込み専用であることをより明確に伝えます。bytes.Reader を使用することで、開発者はこのデータソースが変更されない(書き込まれない)ことをすぐに理解できます。
  2. 適切な抽象化の利用: bytes.Readerio.Reader インターフェースを実装しており、binary.Read が期待するインターフェースに完全に合致します。不要な機能(書き込み)を持つ bytes.Buffer を使うよりも、より特化した bytes.Reader を使う方が、設計上も優れています。
  3. 潜在的な効率性: bytes.Reader は内部的に元のバイトスライスへの参照を持つため、bytes.Buffer のように内部バッファを動的に管理する必要がありません。これにより、特に大きなデータセットを扱う場合や、頻繁に読み込み操作が行われる場合に、わずかながらパフォーマンス上の利点がある可能性があります。ただし、この例のような小さなデータでは、その差はほとんど無視できるレベルです。

この変更は、機能的なバグ修正ではなく、コードの可読性、意図の明確化、およびGo言語のイディオムに沿った改善と見なされます。

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

変更は src/pkg/encoding/binary/example_test.go ファイルの1箇所のみです。

--- a/src/pkg/encoding/binary/example_test.go
+++ b/src/pkg/encoding/binary/example_test.go
@@ -42,7 +42,7 @@ func ExampleWrite_multi() {
 func ExampleRead() {
 	var pi float64
 	b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
-	buf := bytes.NewBuffer(b)
+	buf := bytes.NewReader(b)
 	err := binary.Read(buf, binary.LittleEndian, &pi)
 	if err != nil {
 		fmt.Println("binary.Read failed:", err)

コアとなるコードの解説

変更された行は以下の通りです。

  • 変更前: buf := bytes.NewBuffer(b)
    • バイトスライス b を初期データとして持つ bytes.Buffer の新しいインスタンスを作成し、buf 変数に代入しています。
  • 変更後: buf := bytes.NewReader(b)
    • バイトスライス b からデータを読み込むための bytes.Reader の新しいインスタンスを作成し、buf 変数に代入しています。

この変更により、binary.Read 関数に渡される io.Reader の具体的な実装が bytes.Buffer から bytes.Reader に変わりました。機能的な振る舞いは同じですが、コードの意図がより明確になり、読み込み専用の操作に特化した型が使用されるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコード (特に src/pkg/encoding/binary/example_test.go および src/pkg/bytes/buffer.go, src/pkg/bytes/reader.go)
  • Go言語のコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/13274043 (これはコミットメッセージに記載されているリンクであり、変更の背景を理解する上で非常に有用です。)
  • Go言語のコミュニティにおける議論 (Stack Overflow, Go Forumなど)