[インデックス 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言語には、len
、cap
、new
、make
など、言語自体に組み込まれた関数があります。print
も初期には組み込み関数として存在しましたが、その役割は限定的であり、最終的にはfmt
パッケージに置き換えられる運命にありました。 - 標準エラー出力 (
os.Stderr
): プログラムの診断メッセージやエラーメッセージが出力されるストリームです。組み込みのprint()
関数は、デフォルトでこのストリームに出力していました。
技術的詳細
このコミットの技術的な核心は、Go言語の出力メカニズムの標準化です。
-
print()
からfmt
への移行:- 組み込みの
print()
関数は、その柔軟性の低さ(フォーマット制御ができない、出力先が標準エラーに固定されるなど)から、より強力なfmt
パッケージに置き換えられました。 fmt.Printf
はC言語のprintf
と同様に、フォーマット指定子(例:%s
、%d
)を使用して多様なデータ型を整形して出力できます。fmt.Println
は引数をスペースで区切り、最後に改行を追加して出力します。fmt.Fprintf
は、os.Stderr
のような任意のio.Writer
インターフェースを実装するオブジェクトに対してフォーマットされた出力を書き込むことができます。これにより、出力先を柔軟に制御できるようになります。
- 組み込みの
-
import
文の調整:print()
が組み込み関数であったため、以前はimport
なしで直接使用できました。fmt
パッケージの関数を使用するためには、import "fmt"
が必要になります。これにより、fmt.Printf
のようにパッケージ名をプレフィックスとして付ける必要があります。コミットメッセージにある「generating a little clumsiness around "import"」とは、この変更によってimport
文の追加と関数呼び出しの変更が必要になることを指しています。doc/progs/helloworld.go
のように、import fmt "fmt"
のようにエイリアスを明示的に指定する例も追加されていますが、これは冗長であり、通常はimport "fmt"
と記述します。
-
サンプルコードの更新:
doc/go_tutorial.txt
のチュートリアル本文が更新され、print()
の言及が削除され、fmt.Printf
の使用が強調されています。doc/progs/helloworld2.go
やdoc/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.Printf
やfmt.Println
、fmt.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.go
やcat_rot13.go
のように、エラーメッセージの出力にはfmt.Fprintf(os.Stderr, ...)
が使用され、標準エラーへの出力が明示されました。helloworld2.go
とprintf.go
は完全に削除されました。
doc/progs/run
:- 削除された
helloworld2.go
とprintf.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言語の出力処理が、デバッグ用の簡易的な組み込み関数から、より構造化され、柔軟で、標準的なライブラリ関数へと移行したことを明確に示しています。
関連リンク
- Go言語の
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt - Go言語の
os
パッケージのドキュメント (特にos.Stderr
): https://pkg.go.dev/os
参考にした情報源リンク
- Stack Overflow: Why does Go have built-in print and println functions? https://stackoverflow.com/questions/1000000/why-does-go-have-built-in-print-and-println-functions
- Go Wiki: Builtin functions https://go.dev/doc/effective_go#builtin
- Go Wiki: Go's Printf family https://go.dev/doc/effective_go#printf
- GitHub: proposal: make printf a builtin function https://github.com/golang/go/issues/1137