[インデックス 11155] ファイルの概要
このコミットは、Go言語の標準ライブラリであるbytes
パッケージ内のBuffer
型におけるWrite
メソッドのコードを修正し、WriteString
メソッドのコードと一貫性を持たせることを目的としています。具体的には、copy
関数の戻り値を直接Write
メソッドの戻り値として利用することで、冗長な変数宣言と代入を排除し、コードの簡潔性と可読性を向上させています。
コミット
commit 87ceb0cec73b93064be4b65da6bee265addc2027
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Fri Jan 13 11:48:57 2012 -0800
bytes: make Write and WriteString code look the same
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5540056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/87ceb0cec73b93064be4b65da6bee265addc2027
元コミット内容
bytes: make Write and WriteString code look the same
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5540056
変更の背景
Go言語のbytes
パッケージには、可変長バイトバッファを提供するBuffer
型があります。このBuffer
型には、バイトスライスを書き込むためのWrite
メソッドと、文字列を書き込むためのWriteString
メソッドが存在します。
コミット前のWrite
メソッドの実装は、copy
関数でデータをコピーした後、別途len(p)
を戻り値として返していました。一方、WriteString
メソッドは、copy
関数の戻り値を直接利用して書き込んだバイト数を返していました。このわずかな実装の違いは、機能的には同じ目的(書き込んだバイト数を返す)を達成しているにもかかわらず、コードの見た目とパターンに一貫性がない状態でした。
このコミットの背景には、Go言語のコードベース全体で一貫性のあるコーディングスタイルとパターンを維持しようとする意図があります。特に、類似の機能を持つメソッドは、可能な限り同様のコード構造を持つべきであるという原則に基づいています。これにより、コードの可読性が向上し、開発者が異なるメソッドの実装を理解する際の認知負荷が軽減されます。
前提知識の解説
bytes.Buffer
bytes.Buffer
は、Go言語の標準ライブラリbytes
パッケージで提供される型で、可変長のバイトバッファを実装しています。これは、バイトスライスを効率的に操作するための便利なツールであり、特にI/O操作や文字列操作で頻繁に利用されます。Buffer
のゼロ値はすぐに使用できる空のバッファであり、明示的な初期化は不要です。
Write
メソッドとWriteString
メソッド
-
func (b *Buffer) Write(p []byte) (n int, err error)
: このメソッドは、バイトスライスp
の内容をバッファb
の末尾に追加します。n
は書き込まれたバイト数(通常はlen(p)
)、err
はエラー情報(bytes.Buffer
のWrite
メソッドは常にnil
を返します)を返します。 -
func (b *Buffer) WriteString(s string) (n int, err error)
: このメソッドは、文字列s
の内容をバッファb
の末尾に追加します。n
は書き込まれたバイト数(通常はlen(s)
)、err
はエラー情報(bytes.Buffer
のWriteString
メソッドも常にnil
を返します)を返します。
copy
関数
Go言語の組み込み関数であるcopy
は、ソーススライスからデスティネーションスライスへ要素をコピーします。そのシグネチャはfunc copy(dst, src []Type) int
です。copy
関数は、実際にコピーされた要素の数を返します。これは、デスティネーションスライスまたはソーススライスの長さの小さい方になります。bytes.Buffer
のWrite
やWriteString
メソッドの文脈では、copy
は常にソーススライス(p
または[]byte(s)
)の全てのバイトをコピーできるため、len(p)
またはlen(s)
と同じ値を返します。
技術的詳細
このコミットの技術的な核心は、bytes.Buffer
のWrite
メソッドにおける戻り値の処理方法の変更です。
変更前は、Write
メソッド内でcopy(b.buf[m:], p)
を実行した後、len(p)
を明示的にreturn
していました。
// 変更前
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
copy(b.buf[m:], p) // ここでコピーを実行
return len(p), nil // コピーされたバイト数を別途返す
}
一方、WriteString
メソッドは、copy
関数の戻り値を直接利用していました。
// WriteString (変更前も同様のロジック)
func (b *Buffer) WriteString(s string) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(s))
return copy(b.buf[m:], []byte(s)), nil // copyの戻り値を直接返す
}
copy
関数は、コピーされたバイト数をint
型で返します。bytes.Buffer
のWrite
メソッドでは、grow
によってバッファの容量が確保されているため、copy(b.buf[m:], p)
は常にlen(p)
バイトをコピーし、その値を返します。したがって、copy
の戻り値とlen(p)
は常に同じ値になります。
この事実を利用し、コミットではWrite
メソッドを以下のように変更しました。
// 変更後
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
return copy(b.buf[m:], p), nil // copyの戻り値を直接返す
}
この変更により、Write
メソッドはWriteString
メソッドと全く同じパターンで書き込みバイト数を返すようになりました。これは、コードの冗長性を排除し、より簡潔でGoらしい(idiomatic Go)記述に近づけるためのリファクタリングです。機能的な変更は一切なく、パフォーマンスへの影響もありません。純粋にコードのスタイルと一貫性を改善するための変更です。
コアとなるコードの変更箇所
--- a/src/pkg/bytes/buffer.go
+++ b/src/pkg/bytes/buffer.go
@@ -97,8 +97,7 @@ func (b *Buffer) grow(n int) int {
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
- copy(b.buf[m:], p)
- return len(p), nil
+ return copy(b.buf[m:], p), nil
}
// WriteString appends the contents of s to the buffer. The return
コアとなるコードの解説
変更はsrc/pkg/bytes/buffer.go
ファイルのBuffer
型に属するWrite
メソッド内で行われました。
-
削除された行:
copy(b.buf[m:], p) return len(p), nil
この2行は、まず
copy
関数を呼び出してバイトスライスp
の内容をバッファにコピーし、その後にlen(p)
とnil
(エラーなし)を戻り値として返していました。 -
追加された行:
return copy(b.buf[m:], p), nil
この1行は、
copy
関数の呼び出しと、その戻り値(コピーされたバイト数)およびnil
エラーを直接return
文で返すように変更されました。
この変更により、copy
関数の戻り値がWrite
メソッドのn
(書き込まれたバイト数)として直接利用されるようになり、コードが1行削減され、より簡潔になりました。これは、copy
関数が常に実際にコピーされたバイト数を返すという特性と、bytes.Buffer.Write
が常にlen(p)
バイトをコピーできるという前提に基づいています。
関連リンク
参考にした情報源リンク
- Go言語
bytes
パッケージ ドキュメント: https://pkg.go.dev/bytes - Go言語
copy
関数 ドキュメント: https://pkg.go.dev/builtin#copy - Go言語
bytes.Buffer.Write
メソッド ドキュメント: https://pkg.go.dev/bytes#Buffer.Write - Go言語
bytes.Buffer.WriteString
メソッド ドキュメント: https://pkg.go.dev/bytes#Buffer.WriteString