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

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

このコミットは、Go言語の公式ドキュメントに含まれるプレイグラウンドのサンプルコードにおいて、println および print といった組み込み関数から、標準ライブラリの fmt.Println 関数への置き換えを行ったものです。具体的には、doc/play/fib.godoc/play/sieve.godoc/play/solitaire.godoc/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言語には、初期の頃からprintlnprintといった組み込み関数が存在していました。これらはデバッグや簡単な出力には便利でしたが、Goの標準ライブラリであるfmtパッケージが提供するfmt.Printlnfmt.Printfといった関数に比べて、機能が限定的でした。

具体的には、printlnprintは以下の点で劣っていました。

  1. フォーマット機能の欠如: fmtパッケージの関数は、%d%sのようなフォーマット指定子を使って、様々な型の値を整形して出力する機能を提供します。printlnにはこれがありません。
  2. エラーハンドリングの欠如: fmt.Printlnは書き込みバイト数とエラーを返しますが、printlnは何も返しません。これにより、出力処理が成功したかどうかの確認や、エラー発生時の適切なハンドリングができません。
  3. 一貫性の問題: Goの標準ライブラリは、その設計思想として「明示的であること」を重視します。printlnのような組み込み関数は、あたかも魔法のように動作するように見え、Goの他の部分との一貫性に欠けるという側面がありました。fmt.Printlnfmtパッケージに属していることが明確であり、Goのモジュール性やパッケージ指向の原則に合致します。
  4. 将来的な互換性: Go言語の進化の過程で、組み込み関数よりも標準ライブラリの関数が推奨される傾向にありました。これは、言語のコア部分をスリムに保ち、よりリッチな機能はライブラリとして提供するという設計哲学に基づいています。

このコミットは、Goの公式ドキュメントやサンプルコードにおいて、より推奨されるfmtパッケージの利用を促進し、コードの一貫性と品質を向上させることを目的としています。特に、Go Playgroundの例はGo言語の学習者が最初に触れるコードであるため、ベストプラクティスを示すことが重要でした。

前提知識の解説

Go言語の組み込み関数 (println, print)

Go言語には、言語仕様の一部として定義されている「組み込み関数 (built-in functions)」がいくつか存在します。printlnprintもその一つでした。これらは、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/printfmt.Println の違い

特徴println / print (組み込み関数)fmt.Println (fmtパッケージ関数)
パッケージなし (組み込み)fmtパッケージ
インポート不要import "fmt" が必要
フォーマット限定的 (スペース区切り、改行のみ)柔軟 (フォーマット指定子、カスタム型対応)
戻り値なし(n int, err error) (書き込みバイト数, エラー)
エラーハンドリング不可能可能
用途デバッグ、簡単な出力一般的な出力、ログ、整形された出力

なぜ fmt.Println が推奨されるのか

  1. 堅牢性: fmt.Printlnは出力処理が失敗した場合にエラーを返します。これにより、ディスク容量不足、パーミッションの問題、ネットワークエラー(出力先がネットワークの場合)など、様々な問題に対応できます。printlnはエラーを返さないため、出力が実際に行われたかどうかを知る術がありません。
  2. 柔軟性: fmtパッケージは、fmt.Printfのような関数を通じて、数値の桁数指定、浮動小数点数の精度指定、文字列のパディングなど、高度なフォーマット機能を提供します。これは、ログ出力やレポート生成など、整形された出力が必要な場合に不可欠です。
  3. 一貫性: Goの標準ライブラリは、その設計において一貫性を重視します。fmtパッケージは、GoのI/Oインターフェース(io.Writerなど)と密接に連携しており、ファイル、ネットワーク接続、メモリバッファなど、様々な出力先に統一された方法で書き込むことができます。printlnはこのようなエコシステムから孤立しています。
  4. 可読性と保守性: import "fmt"という記述は、コードが外部パッケージに依存していることを明示します。これにより、コードの依存関係が明確になり、可読性と保守性が向上します。
  5. 将来性: Go言語の進化において、組み込み関数は最小限に保たれ、よりリッチな機能は標準ライブラリとして提供される傾向にあります。fmtパッケージはGoの標準的な出力メカニズムとして確立されており、将来にわたってサポートされ続けることが期待されます。

このコミットは、Go Playgroundのサンプルコードという、Go言語の入門者が最初に触れる部分において、これらのベストプラクティスを適用することで、Go言語の正しい使い方を啓蒙する役割も果たしています。

コメントの変更について

doc/play/solitaire.godoc/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 {

コアとなるコードの解説

各ファイルの変更は、以下のパターンに従っています。

  1. import "fmt" の追加: package main の直後に import "fmt" が追加されています。これは、fmtパッケージの関数を使用するために必須です。Goでは、使用しないパッケージをインポートするとコンパイルエラーになるため、この追加はfmtパッケージの関数が実際に使用されることを示しています。

  2. 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言語の推奨される出力方法に準拠するようになりました。
  3. コメントの整形: doc/play/solitaire.godoc/play/tree.go では、コメント内の行末のバックスラッシュが削除され、コメントの改行がより自然な形になっています。これはコードの機能には影響しませんが、コードの可読性を向上させるための一般的なクリーンアップです。

これらの変更は、Go言語のコードベース全体で一貫したスタイルとベストプラクティスを適用しようとする努力の一環であり、特に学習者向けの公式サンプルコードにおいて、正しい習慣を奨励する上で重要な意味を持ちます。

関連リンク

参考にした情報源リンク

  • Go言語のprintlnfmt.Printlnに関する議論(当時の情報を含む可能性のあるフォーラムやブログ記事)
    • Go言語の進化に関する公式ブログやリリースノート(Go 1.0リリース周辺の変更点など)
    • Stack OverflowなどのQ&Aサイトでの関連質問と回答
    • Go言語の設計思想に関する記事