[インデックス 14492] ファイルの概要
このコミットは、Go言語の公式ドキュメントに含まれるプレイグラウンドのサンプルコードにおいて、println
および print
といった組み込み関数から、標準ライブラリの fmt.Println
関数への置き換えを行ったものです。具体的には、doc/play/fib.go
、doc/play/sieve.go
、doc/play/solitaire.go
、doc/play/tree.go
の4つのファイルが変更されています。
コミット
- コミットハッシュ:
a5e10edc34ecfc8173509fabda0998b0cd518da7
- 作者: Brad Fitzpatrick bradfitz@golang.org
- コミット日時: 2012年11月26日 月曜日 13:05:18 -0800
- コミットメッセージ:
doc/play: don't use println in examples R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6849105
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a5e10edc34ecfc8173509fabda0998b0cd518da7
元コミット内容
doc/play: don't use println in examples
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6849105
変更の背景
この変更の背景には、Go言語における出力関数の推奨される利用方法の確立があります。Go言語には、初期の頃からprintln
やprint
といった組み込み関数が存在していました。これらはデバッグや簡単な出力には便利でしたが、Goの標準ライブラリであるfmt
パッケージが提供するfmt.Println
やfmt.Printf
といった関数に比べて、機能が限定的でした。
具体的には、println
やprint
は以下の点で劣っていました。
- フォーマット機能の欠如:
fmt
パッケージの関数は、%d
や%s
のようなフォーマット指定子を使って、様々な型の値を整形して出力する機能を提供します。println
にはこれがありません。 - エラーハンドリングの欠如:
fmt.Println
は書き込みバイト数とエラーを返しますが、println
は何も返しません。これにより、出力処理が成功したかどうかの確認や、エラー発生時の適切なハンドリングができません。 - 一貫性の問題: Goの標準ライブラリは、その設計思想として「明示的であること」を重視します。
println
のような組み込み関数は、あたかも魔法のように動作するように見え、Goの他の部分との一貫性に欠けるという側面がありました。fmt.Println
はfmt
パッケージに属していることが明確であり、Goのモジュール性やパッケージ指向の原則に合致します。 - 将来的な互換性: Go言語の進化の過程で、組み込み関数よりも標準ライブラリの関数が推奨される傾向にありました。これは、言語のコア部分をスリムに保ち、よりリッチな機能はライブラリとして提供するという設計哲学に基づいています。
このコミットは、Goの公式ドキュメントやサンプルコードにおいて、より推奨されるfmt
パッケージの利用を促進し、コードの一貫性と品質を向上させることを目的としています。特に、Go Playgroundの例はGo言語の学習者が最初に触れるコードであるため、ベストプラクティスを示すことが重要でした。
前提知識の解説
Go言語の組み込み関数 (println
, print
)
Go言語には、言語仕様の一部として定義されている「組み込み関数 (built-in functions)」がいくつか存在します。println
とprint
もその一つでした。これらは、import
文なしで直接コード内で使用でき、引数を標準出力に出力する機能を提供します。
print(args ...Type)
: 引数をスペース区切りで出力します。改行はされません。println(args ...Type)
: 引数をスペース区切りで出力し、最後に改行を追加します。
これらの関数は、主にデバッグ用途や非常にシンプルなスクリプトでの利用を想定していましたが、Goのバージョンが上がるにつれて、より強力で柔軟なfmt
パッケージの関数が推奨されるようになりました。
fmt
パッケージとfmt.Println
fmt
パッケージは、Go言語の標準ライブラリの一部であり、フォーマットされたI/O(入出力)機能を提供します。これは、C言語のprintf
やPythonのprint
関数に似た機能を提供し、様々なデータ型を文字列に変換して出力したり、文字列から値を読み取ったりすることができます。
fmt
パッケージの主な出力関数には以下があります。
fmt.Print(a ...interface{}) (n int, err error)
: 引数をデフォルトのフォーマットで出力します。スペース区切りで、改行はされません。fmt.Println(a ...interface{}) (n int, err error)
: 引数をデフォルトのフォーマットで出力し、各引数の間にスペースを挿入し、最後に改行を追加します。fmt.Printf(format string, a ...interface{}) (n int, err error)
: フォーマット文字列に基づいて引数を整形して出力します。改行は自動的に追加されません。
これらの関数は、出力されたバイト数とエラー情報を返すため、より堅牢なエラーハンドリングが可能です。また、fmt.Stringer
インターフェースを実装したカスタム型に対しても、適切に動作します。
Go Playground
Go Playgroundは、Go言語のコードをブラウザ上で記述、実行、共有できるオンラインツールです。Goの公式ウェブサイト(golang.org)で提供されており、Go言語の学習や簡単なコードのテストに広く利用されています。このコミットで変更されたファイルは、Go Playgroundのサンプルコードとして使用されるものでした。
技術的詳細
このコミットの核心は、Go言語における出力処理のベストプラクティスへの移行です。
println
/print
と fmt.Println
の違い
特徴 | println / print (組み込み関数) | fmt.Println (fmtパッケージ関数) |
---|---|---|
パッケージ | なし (組み込み) | fmt パッケージ |
インポート | 不要 | import "fmt" が必要 |
フォーマット | 限定的 (スペース区切り、改行のみ) | 柔軟 (フォーマット指定子、カスタム型対応) |
戻り値 | なし | (n int, err error) (書き込みバイト数, エラー) |
エラーハンドリング | 不可能 | 可能 |
用途 | デバッグ、簡単な出力 | 一般的な出力、ログ、整形された出力 |
なぜ fmt.Println
が推奨されるのか
- 堅牢性:
fmt.Println
は出力処理が失敗した場合にエラーを返します。これにより、ディスク容量不足、パーミッションの問題、ネットワークエラー(出力先がネットワークの場合)など、様々な問題に対応できます。println
はエラーを返さないため、出力が実際に行われたかどうかを知る術がありません。 - 柔軟性:
fmt
パッケージは、fmt.Printf
のような関数を通じて、数値の桁数指定、浮動小数点数の精度指定、文字列のパディングなど、高度なフォーマット機能を提供します。これは、ログ出力やレポート生成など、整形された出力が必要な場合に不可欠です。 - 一貫性: Goの標準ライブラリは、その設計において一貫性を重視します。
fmt
パッケージは、GoのI/Oインターフェース(io.Writer
など)と密接に連携しており、ファイル、ネットワーク接続、メモリバッファなど、様々な出力先に統一された方法で書き込むことができます。println
はこのようなエコシステムから孤立しています。 - 可読性と保守性:
import "fmt"
という記述は、コードが外部パッケージに依存していることを明示します。これにより、コードの依存関係が明確になり、可読性と保守性が向上します。 - 将来性: Go言語の進化において、組み込み関数は最小限に保たれ、よりリッチな機能は標準ライブラリとして提供される傾向にあります。
fmt
パッケージはGoの標準的な出力メカニズムとして確立されており、将来にわたってサポートされ続けることが期待されます。
このコミットは、Go Playgroundのサンプルコードという、Go言語の入門者が最初に触れる部分において、これらのベストプラクティスを適用することで、Go言語の正しい使い方を啓蒙する役割も果たしています。
コメントの変更について
doc/play/solitaire.go
と doc/play/tree.go
では、コードの変更に加えて、コメントの整形も行われています。具体的には、行末のバックスラッシュ(\
)が削除され、コメントがより自然な改行で表示されるように修正されています。これは、コードの機能には影響しませんが、可読性を向上させるための一般的なコードスタイル改善の一環です。
コアとなるコードの変更箇所
doc/play/fib.go
--- a/doc/play/fib.go
+++ b/doc/play/fib.go
@@ -1,5 +1,7 @@
package main
+import "fmt"
+
// fib returns a function that returns
// successive Fibonacci numbers.
func fib() func() int {
@@ -13,5 +15,5 @@ func fib() func() int {
func main() {
f := fib()
// Function calls are evaluated left-to-right.
- println(f(), f(), f(), f(), f())
+ fmt.Println(f(), f(), f(), f(), f())
}
doc/play/sieve.go
--- a/doc/play/sieve.go
+++ b/doc/play/sieve.go
@@ -2,6 +2,8 @@
package main
+import "fmt"
+
// Send the sequence 2, 3, 4, ... to channel 'ch'.
func Generate(ch chan<- int) {
for i := 2; ; i++ {
@@ -26,7 +28,7 @@ func main() {
go Generate(ch) // Launch Generate goroutine.
for i := 0; i < 10; i++ {
prime := <-ch
- print(prime, "\n")
+ fmt.Println(prime)
ch1 := make(chan int)
go Filter(ch, ch1, prime)
ch = ch1
doc/play/solitaire.go
--- a/doc/play/solitaire.go
+++ b/doc/play/solitaire.go
@@ -28,7 +28,7 @@ var board = []rune(\
...........\
`)
-// center is the position of the center hole if
+// center is the position of the center hole if
// there is a single one; otherwise it is -1.\
var center int
@@ -47,7 +47,7 @@ func init() {\
var moves int // number of times move is called
-// move tests if there is a peg at position pos that
+// move tests if there is a peg at position pos that
// can jump over another peg in direction dir. If the
// move is valid, it is executed and move returns true.\
// Otherwise, move returns false.\
@@ -69,11 +69,11 @@ func unmove(pos, dir int) {\
board[pos+2*dir] = '○'
}
-// solve tries to find a sequence of moves such that
-// there is only one peg left at the end; if center is
+// solve tries to find a sequence of moves such that
+// there is only one peg left at the end; if center is
// >= 0, that last peg must be in the center position.\
// If a solution is found, solve prints the board after
-// each move in a backward fashion (i.e., the last
+// each move in a backward fashion (i.e., the last
// board position is printed first, all the way back to\
// the starting board position).\
func solve() bool {\
@@ -89,7 +89,7 @@ func solve() bool {\
// see if this new board has a solution
if solve() {
unmove(pos, dir)
- println(string(board))
+ fmt.Println(string(board))
return true
}
unmove(pos, dir)
@@ -102,7 +102,7 @@ func solve() bool {\
// tried each possible move
if n == 1 && (center < 0 || last == center) {
// there's only one peg left
- println(string(board))
+ fmt.Println(string(board))
return true
}
// no solution found for this board
doc/play/tree.go
--- a/doc/play/tree.go
+++ b/doc/play/tree.go
@@ -2,7 +2,7 @@
// express concurrent concepts, such as
// this binary tree comparison.\
//\
-// Trees may be of different shapes, \
+// Trees may be of different shapes,
// but have the same contents. For example:\
//\
// 4 6
@@ -29,7 +29,7 @@ type Tree struct {\
Right *Tree
}
-// Walk traverses a tree depth-first, \
+// Walk traverses a tree depth-first,
// sending each Value on a channel.\
func Walk(t *Tree, ch chan int) {
if t == nil {
コアとなるコードの解説
各ファイルの変更は、以下のパターンに従っています。
-
import "fmt"
の追加:package main
の直後にimport "fmt"
が追加されています。これは、fmt
パッケージの関数を使用するために必須です。Goでは、使用しないパッケージをインポートするとコンパイルエラーになるため、この追加はfmt
パッケージの関数が実際に使用されることを示しています。 -
println(...)
またはprint(...)
のfmt.Println(...)
への置き換え:doc/play/fib.go
では、println(f(), f(), f(), f(), f())
がfmt.Println(f(), f(), f(), f(), f())
に変更されています。doc/play/sieve.go
では、print(prime, "\n")
がfmt.Println(prime)
に変更されています。print
と明示的な改行文字の組み合わせが、fmt.Println
のデフォルトの動作(引数間にスペースを挿入し、最後に改行を追加)に置き換えられています。doc/play/solitaire.go
では、println(string(board))
がfmt.Println(string(board))
に変更されています。 これらの変更により、Go Playgroundのサンプルコードが、Go言語の推奨される出力方法に準拠するようになりました。
-
コメントの整形:
doc/play/solitaire.go
とdoc/play/tree.go
では、コメント内の行末のバックスラッシュが削除され、コメントの改行がより自然な形になっています。これはコードの機能には影響しませんが、コードの可読性を向上させるための一般的なクリーンアップです。
これらの変更は、Go言語のコードベース全体で一貫したスタイルとベストプラクティスを適用しようとする努力の一環であり、特に学習者向けの公式サンプルコードにおいて、正しい習慣を奨励する上で重要な意味を持ちます。
関連リンク
- Go言語公式ドキュメント: https://golang.org/doc/
- Go Playground: https://play.golang.org/
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt
参考にした情報源リンク
- Go言語の
println
とfmt.Println
に関する議論(当時の情報を含む可能性のあるフォーラムやブログ記事)- Go言語の進化に関する公式ブログやリリースノート(Go 1.0リリース周辺の変更点など)
- Stack OverflowなどのQ&Aサイトでの関連質問と回答
- Go言語の設計思想に関する記事