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

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

このコミットは、Go言語の初期開発段階において、チュートリアルおよびサンプルプログラムから組み込みの print() 関数を削除し、標準ライブラリの fmt パッケージによる出力に移行する変更を記録しています。これにより、Go言語の出力メカニズムが統一され、より堅牢な fmt パッケージの使用が推奨されるようになりました。

コミット

commit bdbb3b455e9bccb6c0994ff3a8216477f18f70fb
Author: Rob Pike <r@golang.org>
Date:   Wed Mar 18 14:09:16 2009 -0700

    remove print() from the tutorial, generating a little clumsiness around "import"
    
    R=rsc,gri
    DELTA=103  (36 added, 33 deleted, 34 changed)
    OCL=26442
    CL=26491

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

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

元コミット内容

このコミットの目的は、Go言語のチュートリアルと関連するサンプルコードから、組み込みの print() 関数を削除することです。これにより、import 文の扱いに関して若干の不便さが生じるものの、言語設計の一貫性を保つための重要な変更でした。

変更の背景

Go言語の初期段階では、デバッグやブートストラップの目的で print() および println() といった組み込み関数が存在していました。これらは引数を実装依存の方法でフォーマットし、標準エラー出力に書き出すものでした。しかし、これらの組み込み関数は長期的に言語に残ることが保証されておらず、より汎用的な出力やフォーマットされた出力のためには、標準ライブラリの fmt パッケージが推奨されていました。

このコミットは、Go言語の設計思想を反映し、fmt パッケージを標準的な出力方法として確立するためのステップです。チュートリアルやサンプルコードから print() を排除することで、開発者が最初から fmt パッケージの利用に慣れることを促し、将来的な言語の安定性と一貫性を確保することを目的としています。

前提知識の解説

  • Go言語のパッケージシステム: Go言語では、コードは「パッケージ」という単位で整理されます。main パッケージは実行可能なプログラムのエントリポイントを含み、他のパッケージを import することでその機能を利用できます。
  • fmt パッケージ: fmt は "format" の略で、Go言語の標準ライブラリの一部です。フォーマットされたI/O(入出力)を提供し、Printf(フォーマット指定子を使った出力)、Println(改行付き出力)、Print(改行なし出力)、Fprintf(指定されたio.Writerへの出力)などの関数を提供します。これらはC言語の printf ファミリー関数に似ています。
  • 組み込み関数 (built-in functions): Go言語には、lencapnewmake など、言語自体に組み込まれた関数があります。print も初期には組み込み関数として存在しましたが、その役割は限定的であり、最終的には fmt パッケージに置き換えられる運命にありました。
  • 標準エラー出力 (os.Stderr): プログラムの診断メッセージやエラーメッセージが出力されるストリームです。組み込みの print() 関数は、デフォルトでこのストリームに出力していました。

技術的詳細

このコミットの技術的な核心は、Go言語の出力メカニズムの標準化です。

  1. print() から fmt への移行:

    • 組み込みの print() 関数は、その柔軟性の低さ(フォーマット制御ができない、出力先が標準エラーに固定されるなど)から、より強力な fmt パッケージに置き換えられました。
    • fmt.Printf はC言語の printf と同様に、フォーマット指定子(例: %s%d)を使用して多様なデータ型を整形して出力できます。
    • fmt.Println は引数をスペースで区切り、最後に改行を追加して出力します。
    • fmt.Fprintf は、os.Stderr のような任意の io.Writer インターフェースを実装するオブジェクトに対してフォーマットされた出力を書き込むことができます。これにより、出力先を柔軟に制御できるようになります。
  2. import 文の調整:

    • print() が組み込み関数であったため、以前は import なしで直接使用できました。
    • fmt パッケージの関数を使用するためには、import "fmt" が必要になります。これにより、fmt.Printf のようにパッケージ名をプレフィックスとして付ける必要があります。コミットメッセージにある「generating a little clumsiness around "import"」とは、この変更によって import 文の追加と関数呼び出しの変更が必要になることを指しています。
    • doc/progs/helloworld.go のように、import fmt "fmt" のようにエイリアスを明示的に指定する例も追加されていますが、これは冗長であり、通常は import "fmt" と記述します。
  3. サンプルコードの更新:

    • doc/go_tutorial.txt のチュートリアル本文が更新され、print() の言及が削除され、fmt.Printf の使用が強調されています。
    • doc/progs/helloworld2.godoc/progs/printf.go のように、print()fmt.Printf の特定の側面をデモンストレーションしていた古いサンプルファイルが削除されました。
    • cat.go, cat_rot13.go, helloworld.go, helloworld3.go, server.go, server1.go, sieve.go, sieve1.go, sortmain.go, strings.go, sum.go など、多数のサンプルプログラムで print() の呼び出しが fmt.Printffmt.Printlnfmt.Fprintf に置き換えられています。特にエラー出力には fmt.Fprintf(os.Stderr, ...) が用いられています。

この変更は、Go言語が初期の実験段階から、より成熟した標準的なライブラリと慣習を持つ言語へと進化する過程の一部を示しています。

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

このコミットは、主に doc/ ディレクトリ以下のチュートリアル文書とサンプルプログラムに影響を与えています。

  • doc/go_tutorial.txt:
    • print() 関数に関する記述が削除され、fmt.Printf の使用が推奨されるように変更されました。
    • helloworld2.go の例が削除され、fmt パッケージの Printf を使用する helloworld.go が主要な例として残されました。
    • import 文に関する説明が更新され、パッケージのインポート方法がより明確に記述されました。
  • doc/progs/*.go ファイル群:
    • print(...) の呼び出しが、fmt.Printf(...)fmt.Println(...)、または fmt.Fprintf(os.Stderr, ...) に置き換えられました。
    • cat.gocat_rot13.go のように、エラーメッセージの出力には fmt.Fprintf(os.Stderr, ...) が使用され、標準エラーへの出力が明示されました。
    • helloworld2.goprintf.go は完全に削除されました。
  • doc/progs/run:
    • 削除された helloworld2.goprintf.go の実行テストが削除されました。

コアとなるコードの解説

変更の核心は、print() の直接的な呼び出しを fmt パッケージの適切な関数に置き換えることです。

例えば、doc/progs/helloworld.go では、以下の変更が行われました。

変更前:

package main

func main() {
	print("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
}

変更後:

package main

import fmt "fmt"  // Package implementing formatted I/O.

func main() {
	fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
}

この変更により、fmt パッケージがインポートされ、fmt.Printf を使用して文字列がフォーマットされて出力されるようになりました。Printf\n のようなエスケープシーケンスを解釈し、より柔軟な出力が可能です。

また、doc/progs/cat.go のようなファイルでは、エラー出力の変更が見られます。

変更前 (一部):

			print("error reading from ", f.String(), ": ", er.String(), "\n");

変更後 (一部):

			fmt.Fprintf(os.Stderr, "error reading from %s: %s\n", f.String(), er.String());

ここでは、print()fmt.Fprintf(os.Stderr, ...) に置き換えられています。これは、エラーメッセージを標準エラー出力 (os.Stderr) に明示的に書き込むための変更であり、出力のセマンティクスをより正確に表現しています。%s は文字列のフォーマット指定子です。

これらの変更は、Go言語の出力処理が、デバッグ用の簡易的な組み込み関数から、より構造化され、柔軟で、標準的なライブラリ関数へと移行したことを明確に示しています。

関連リンク

参考にした情報源リンク