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

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

このコミットは、Go言語の標準ライブラリ doc/go1.2.txt から、io/ioutil パッケージの DiscardWriteString メソッドが追加されたという記述を削除するものです。この変更は、ユーザーから見てAPIの変更を伴うものではなく、特定の状況下でのみ発生する些細なガベージコレクションの改善に過ぎないため、Go 1.2のリリースノートに記載するほどの重要性がないと判断されました。

コミット

commit 8738dd3ccef1a58b9759c4be1a279b8abe8424f4
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Tue Aug 20 15:35:07 2013 -0700

    doc: remove a insignificant line from go1.2.txt
    
    Not a user-visible API change.  Just a minor garbage
    win in contrived cases.
    
    Also, the package is io/ioutil.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/12987044

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

https://github.com/golang/go/commit/8738dd3ccef1a58b9759c4be1a279b8abe8424f4

元コミット内容

doc: remove a insignificant line from go1.2.txt

これはユーザーから見えるAPIの変更ではない。単に、特殊なケースでのわずかなガベージコレクションの改善である。 また、パッケージは io/ioutil である。

変更の背景

このコミットの背景には、Go 1.2のリリースノート (doc/go1.2.txt) の内容を精査し、ユーザーにとって重要ではない、あるいは誤解を招く可能性のある記述を削除するという意図があります。具体的には、io/ioutil パッケージの DiscardWriteString メソッドが追加されたという記述が削除されました。

元の変更(WriteString の追加)は、io.Discardio.Writer インターフェースを満たすだけでなく、io.StringWriter インターフェースも満たすようにするためのものでした。これにより、WriteString メソッドを持つ型に対して最適化された書き込みを行う際に、io.Discard がその恩恵を受けられるようになりました。しかし、この最適化は「特殊なケースでのわずかなガベージコレクションの改善」に過ぎず、一般的なユーザーが意識するようなAPIの変更や機能追加ではなかったため、リリースノートに記載するほどの重要性はないと判断されました。

Go言語の開発プロセスでは、リリースノートはユーザーが新しいバージョンで何が変わったのかを理解するための重要なドキュメントです。そのため、本当にユーザーに影響のある変更や新機能のみを記載し、内部的な最適化や些細な改善は省略されることがあります。このコミットは、その方針に沿ったドキュメントのクリーンアップの一環と言えます。

前提知識の解説

Go言語の io パッケージと io/ioutil パッケージ

Go言語の io パッケージは、I/Oプリミティブ(入力/出力の基本的な操作)を提供します。これには、データの読み書きを行うためのインターフェース(io.Reader, io.Writer など)が含まれます。

io/ioutil パッケージは、io パッケージの補助的な機能を提供していました。例えば、ファイルの読み書きを簡単に行う関数や、一時ファイルを作成する関数などです。Go 1.16以降、io/ioutil パッケージの機能は io パッケージと os パッケージに統合され、io/ioutil は非推奨となりましたが、このコミットが作成された2013年当時はまだ活発に使用されていました。

io.Discard

io.Discardio.Writer インターフェースを実装した特殊な変数です。この Writer に書き込まれたデータはすべて破棄されます。つまり、どこにも出力されません。これは、例えば、関数の戻り値として io.Writer が期待されるが、実際には出力が不要な場合などに使用されます。

package main

import (
	"io"
	"fmt"
)

func main() {
	// io.Discard に書き込むと、何も出力されない
	n, err := io.Discard.Write([]byte("Hello, world!\n"))
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Printf("Bytes written to Discard: %d\n", n) // 出力: Bytes written to Discard: 14
}

io.StringWriter インターフェース

io.StringWriter インターフェースは、WriteString(s string) (n int, err error) メソッドを持つ型が実装するインターフェースです。このインターフェースを実装することで、文字列を書き込む際に、バイトスライスに変換するオーバーヘッドを避けるなど、より効率的な書き込みが可能になります。

Go 1.2のリリースでは、io.Copyio.WriteString のような関数が、引数として渡された io.Writerio.StringWriter インターフェースも実装している場合に、その最適化された WriteString メソッドを優先的に使用するようになりました。

ガベージコレクション (GC)

ガベージコレクションは、プログラムが動的に確保したメモリのうち、もはや使用されていない(参照されていない)領域を自動的に解放するプロセスです。これにより、プログラマは手動でメモリを管理する手間から解放されます。しかし、GCは実行時に一時的にプログラムの実行を停止させたり(ストップ・ザ・ワールド)、CPUリソースを消費したりするため、そのオーバーヘッドは最小限に抑えることが望ましいです。

このコミットで言及されている「わずかなガベージコレクションの改善」とは、WriteString メソッドが io.Discard に追加されたことで、文字列を io.Discard に書き込む際に、一時的なバイトスライスが生成されなくなり、その結果、GCの負荷がわずかに軽減されるということを指しています。

技術的詳細

このコミットは、Go 1.2のリリースノート (doc/go1.2.txt) から以下の行を削除しています。

ioutil: add WriteString to Discard (CL 12580045).

この行が指しているのは、Goの内部的な変更、具体的には io.Discardio.StringWriter インターフェースを実装するようになったことです。

Go 1.2の変更点として、io.WriteString 関数(これは io パッケージにあります)や、io.Copy の内部実装が改善され、io.Writerio.StringWriter インターフェースも実装している場合、WriteString メソッドを直接呼び出すようになりました。これにより、文字列をバイトスライスに変換してから Write メソッドを呼び出すという、余分なメモリ割り当てとコピーのオーバーヘッドが削減されます。

io.Discard は、元々 Write メソッドを実装していましたが、これは受け取ったバイトスライスを単に破棄するだけでした。WriteString メソッドが io.Discard に追加されたことで、io.Discardio.StringWriter インターフェースを満たすようになります。

// io/ioutil/ioutil.go (Go 1.2当時の実装を想定)
// Discard は io.Writer インターフェースを実装し、書き込まれたデータを破棄する。
type discard int

func (discard) Write(p []byte) (int, error) {
	return len(p), nil
}

// WriteString は io.StringWriter インターフェースを実装し、文字列を破棄する。
func (discard) WriteString(s string) (int, error) {
	return len(s), nil
}

// Discard は、書き込まれたデータを破棄する io.Writer である。
var Discard io.Writer = discard(0)

(注: 実際のGo 1.2の io/ioutil の実装では、Discardio.Writer 型としてエクスポートされており、WriteString メソッドは discard 型に直接追加されていました。これにより、Discard 変数は暗黙的に io.StringWriter インターフェースも満たすことになります。)

この変更により、例えば以下のようなコードが実行された場合、

import (
	"io"
	"fmt"
)

func main() {
	s := "some string data"
	// io.WriteString は、w が io.StringWriter を実装していれば WriteString を呼び出す
	n, err := io.WriteString(io.Discard, s)
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Printf("Bytes written: %d\n", n)
}

io.WriteStrings をバイトスライスに変換することなく、直接 io.DiscardWriteString メソッドを呼び出すようになります。これにより、一時的なバイトスライスのアロケーションが不要になり、ガベージコレクションの対象となるオブジェクトが一つ減るため、特に頻繁に文字列を破棄するような「特殊なケース」において、わずかながらGCの負荷が軽減されるという効果がありました。

しかし、この最適化はGoの内部的な挙動の改善であり、ユーザーがコードを書く上で io.Discard のAPIが変わるわけではありません。また、その性能改善も「わずか」であるため、Go 1.2の主要な変更点としてリリースノートに記載するほどのインパクトはないと判断され、このコミットで削除されることになりました。

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

このコミットは、doc/go1.2.txt ファイルの1行を削除するものです。

--- a/doc/go1.2.txt
+++ b/doc/go1.2.txt
@@ -53,7 +53,6 @@ image/draw: added Drawer, FloydSteinberg and the op.Draw method (CL 10977043).
 image/draw: added Quantizer type (CL 11148043).
 image/gif: added Encode and EncodeAll (CL 10896043).
 io: Copy prioritizes WriterTo over ReaderFrom (CL 9462044).
-ioutil: add WriteString to Discard (CL 12580045).
 net: new build tag netgo for building a pure Go net package (CL 7100050).
 net/http: don't allow sending invalid cookie lines (CL 12204043).
 net/http: allow ReadResponse with nil *Request parameter (CL 9821043).

具体的には、54行目(変更前)にあった以下の行が削除されました。

-ioutil: add WriteString to Discard (CL 12580045).

コアとなるコードの解説

変更されたファイルは doc/go1.2.txt であり、これはGo 1.2のリリースノートのドラフトまたは最終版の一部です。このファイルは、Go言語の新しいバージョンで導入された変更点や新機能をユーザーに伝えるためのドキュメントです。

削除された行は、io/ioutil パッケージの DiscardWriteString メソッドが追加されたことを示していました。この変更自体は、Goの内部的な最適化であり、io.Discardio.StringWriter インターフェースを実装するようになったことを意味します。これにより、文字列を io.Discard に書き込む際のメモリ割り当てが削減され、ガベージコレクションの負荷がわずかに軽減される効果がありました。

しかし、このコミットの目的は、この変更が「ユーザーから見えるAPIの変更ではない」こと、そして「特殊なケースでのわずかなガベージコレクションの改善」に過ぎないため、リリースノートに記載するほどの重要性がないと判断されたことです。したがって、この行を削除することで、リリースノートの記述をより簡潔にし、本当に重要な変更点に焦点を当てるようにしています。

この変更は、コードの機能的な挙動には一切影響を与えません。影響があるのは、Go 1.2のリリースノートの内容のみです。

関連リンク

  • Go 1.2 Release Notes (最終版): https://go.dev/doc/go1.2
    • このコミットによって削除された内容は、最終的なGo 1.2のリリースノートには含まれていません。

参考にした情報源リンク

  • Go 1.2 Release Notes (最終版): https://go.dev/doc/go1.2
  • Goの io パッケージドキュメント: https://pkg.go.dev/io
  • Goの io/ioutil パッケージドキュメント (非推奨): https://pkg.go.dev/io/ioutil
  • Goの io.StringWriter インターフェースに関する議論や変更履歴 (Goのソースコードや関連するCLを辿ることで詳細が得られますが、一般的な情報源としては上記のパッケージドキュメントが起点となります。)
  • 元の変更 (CL 12580045) の詳細 (GoのGerrit Code Reviewシステムで検索可能): https://go.dev/cl/12580045
    • このリンクは、コミットメッセージに記載されている https://golang.org/cl/12987044 とは異なるCL番号ですが、12580045ioutil: add WriteString to Discard の元の変更のCL番号です。
  • このコミットのCL (Code Review) ページ: https://go.dev/cl/12987044