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

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

このコミットは、usr/gri/pretty/selftest2.go ファイルに対する変更です。具体的には、defer println(i, x); という行が defer Fmt.Println(i, x); に修正されています。これは、Go言語の初期開発段階において、6g コンパイラとの互換性を確保するためのテストコードの修正です。

コミット

commit eecce5f13055eaddde6343450b7205cc6f2df286
Author: Robert Griesemer <gri@golang.org>
Date:   Thu Jan 29 15:16:22 2009 -0800

    - make test work with 6g
    
    R=r
    OCL=23821
    CL=23823

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

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

元コミット内容

- make test work with 6g

このコミットの目的は、テストが 6g コンパイラで動作するようにすることです。

変更の背景

このコミットは、Go言語の非常に初期の段階、具体的には2009年1月に作成されました。当時のGo言語はまだ公開されておらず、開発が活発に行われていました。Go言語のコンパイラは、当初 6g (64-bit x86ターゲット), 8g (32-bit x86ターゲット), 5g (ARMターゲット) といった名称で呼ばれていました。

この時期、Go言語の標準ライブラリや組み込み関数の仕様はまだ固まっておらず、println のような組み込み関数と fmt パッケージの Println 関数の挙動や利用方法が進化している最中でした。

コミットメッセージにある「make test work with 6g」という記述から、既存のテストコードが 6g コンパイラで正しく動作しない問題が発生しており、その原因が println 関数の利用方法にあることが示唆されます。おそらく、6g コンパイラの特定のバージョンや設定において、組み込みの println が期待通りに動作しない、あるいは fmt.Println を使用することが推奨されるようになった、といった背景があったと考えられます。

前提知識の解説

Go言語の初期コンパイラ (6g, 8g, 5g)

Go言語は、GoogleでRobert Griesemer, Rob Pike, Ken Thompsonによって開発され、2009年11月に一般公開されました。初期のGo言語のコンパイラは、ターゲットアーキテクチャに基づいて命名されていました。

  • 6g: 64-bit x86 (amd64) アーキテクチャをターゲットとするGoコンパイラ。
  • 8g: 32-bit x86 (i386) アーキテクチャをターゲットとするGoコンパイラ。
  • 5g: ARM アーキテクチャをターゲットとするGoコンパイラ。

これらのコンパイラは、Go言語の初期のツールチェインの一部であり、Go 1.5 (2015年) でツールチェイン全体がGo言語自身で書かれるようになるまで使用されていました。

printlnfmt.Println

Go言語には、出力を行うための関数がいくつか存在します。

  • println() (組み込み関数): これはGo言語に組み込まれた(import なしで利用できる)関数で、デバッグや簡単な出力によく使われます。しかし、その動作は実装依存であり、フォーマットの制御はできません。また、通常は標準エラー出力に書き込まれることが多いです。Go言語の初期には、この println の挙動がコンパイラや環境によって異なることがありました。

  • fmt.Println() (標準ライブラリ fmt パッケージの関数): fmt パッケージは、C言語の printfscanf に似た、フォーマットされたI/O機能を提供します。fmt.Println() は、引数をデフォルトのフォーマットで整形し、標準出力に書き込みます。引数間にはスペースが挿入され、最後に改行が追加されます。この関数は、より安定した、予測可能な出力動作を提供し、Go言語の標準的な出力方法として推奨されています。

このコミットが行われた時期は、println のような組み込み関数の利用が、特定のコンパイラ(この場合は 6g)で問題を引き起こす可能性があったため、より堅牢な fmt.Println への移行が進められていたと考えられます。

技術的詳細

このコミットの技術的な核心は、Go言語の初期における println 組み込み関数と fmt.Println 関数の間の挙動の違い、および 6g コンパイラとの互換性の問題にあります。

selftest2.go は、Go言語の様々な構文や機能のテストを行うためのファイルであり、defer ステートメント内で println を使用していました。defer ステートメントは、関数がリターンする直前に実行される関数呼び出しをスケジュールします。

問題は、6g コンパイラが defer println(i, x); という記述を正しく処理できない、あるいは期待する動作をしない可能性があったことです。これは、println が組み込み関数であるため、コンパイラがその呼び出しをどのように最適化または変換するかに依存します。Go言語の初期段階では、コンパイラの成熟度がまだ低く、このようなエッジケースで問題が発生することがありました。

一方、Fmt.Println (現在の fmt.Println) は、標準ライブラリの一部として提供される関数であり、その実装はより安定しており、コンパイラに依存しない形で動作することが期待されます。fmt パッケージは、Go言語のI/O処理の標準的な方法を提供するために設計されており、コンパイラのバージョンやターゲットアーキテクチャに起因する問題を回避するのに役立ちます。

したがって、この変更は、6g コンパイラでテストが確実に動作するようにするために、組み込みの println から、より堅牢で標準的な fmt.Println へと切り替えるという、実用的な解決策でした。これにより、テストの信頼性が向上し、Go言語のツールチェイン全体の安定化に貢献しました。

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

--- a/usr/gri/pretty/selftest2.go
+++ b/usr/gri/pretty/selftest2.go
@@ -123,7 +123,7 @@ func f3(a *[]int, m map[string] int) {
 	var i string;
 	var x int;
 	for i, x = range m {
-		defer println(i, x);
+		defer Fmt.Println(i, x);
 	}
 }

コアとなるコードの解説

変更は selftest2.go ファイルの f3 関数内で行われています。

元のコード:

defer println(i, x);

この行は、for ループ内でイテレートされる m (map[string] int) の各要素 (i, x) に対して、println 組み込み関数を defer しています。つまり、f3 関数が終了する直前に、ループ内で処理されたすべての (i, x) の値が println によって出力されるようにスケジュールされます。

変更後のコード:

defer Fmt.Println(i, x);

この行では、println 組み込み関数が Fmt.Println (現在の fmt.Println) に置き換えられています。機能的には同様に (i, x) の値を出力しますが、fmt パッケージの関数を使用することで、6g コンパイラとの互換性の問題が解決され、より標準的で予測可能な出力動作が保証されます。

この変更は、Go言語の初期開発におけるコンパイラの成熟度と、標準ライブラリの進化を示す良い例です。特定のコンパイラで問題が発生した場合に、より安定した標準ライブラリの機能に切り替えるという、一般的なソフトウェア開発におけるプラクティスが適用されています。

関連リンク

参考にした情報源リンク