[インデックス 1476] ファイルの概要
このコミットは、Go言語の標準ライブラリにおけるfmt
パッケージの関数名の変更を主に行っています。具体的には、printf
、sprintf
、fprintf
、print
、sprint
、fprint
、println
、sprintln
といった関数が、それぞれPrintf
、Sprintf
、Fprintf
、Print
、Sprint
、Fprint
、Println
、Sprintln
のように、先頭が大文字の形式に変更されています。これはGo言語におけるエクスポートされた(外部から利用可能な)関数名の慣習に合わせた変更です。
コミット
commit 61f33020446aaeabf15dce35882b08f8facb1dd
Author: Rob Pike <r@golang.org>
Date: Thu Jan 15 13:48:11 2009 -0800
printf->Printf etc.
the raw fmt routines will be another, smaller but subtler pass.
R=rsc
DELTA=157 (0 added, 0 deleted, 157 changed)
OCL=22851
CL=22851
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/61f33020446aaeabf15dce35882b08f8facb1dd
元コミット内容
printf->Printf etc.
the raw fmt routines will be another, smaller but subtler pass.
変更の背景
この変更は、Go言語の設計原則とコーディング規約に準拠するためのものです。Go言語では、パッケージ外部に公開される(エクスポートされる)識別子(関数名、変数名、型名など)は、慣習として先頭を大文字にするというルールがあります。これにより、コードを読む際にどの識別子が外部からアクセス可能であるかを一目で判断できます。
コミットメッセージにある「the raw fmt routines will be another, smaller but subtler pass.」という記述は、fmt
パッケージ内のより低レベルな("raw")フォーマットルーチンについては、このコミットとは別の、より細かく微妙な変更が後に行われることを示唆しています。これは、Go言語の進化の初期段階において、APIの整合性と設計の一貫性を確立するための継続的な取り組みの一環であったと考えられます。
前提知識の解説
Go言語の命名規約(Exported Identifiers)
Go言語には、識別子の可視性に関する明確なルールがあります。
- エクスポートされた識別子(Exported Identifiers): 識別子の最初の文字が大文字の場合、その識別子はパッケージの外部からアクセス可能です。これは、他のプログラミング言語における
public
キーワードに相当します。 - エクスポートされない識別子(Unexported Identifiers): 識別子の最初の文字が小文字の場合、その識別子は宣言されたパッケージ内でのみアクセス可能です。これは、他のプログラミング言語における
private
またはinternal
に相当します。
この規約は、Go言語の設計思想である「シンプルさ」と「明示性」を反映しています。fmt.printf
のような小文字で始まる関数名は、Goの慣習に反しており、パッケージ外部から利用されることを意図していないか、あるいは初期の設計段階での一時的な命名であった可能性があります。このコミットは、これらの関数が標準ライブラリの一部として外部に公開されるべきであるという判断に基づき、命名規約に適合させたものです。
fmt
パッケージ
fmt
パッケージは、Go言語におけるフォーマットI/Oを実装するためのパッケージです。C言語のprintf
やscanf
に似た機能を提供し、様々なデータ型を文字列に変換したり、文字列からデータを解析したりする機能を持っています。
Print
系関数: 引数を標準出力に表示します。Println
系関数: 引数を標準出力に表示し、最後に改行を追加します。Printf
系関数: フォーマット文字列に基づいて引数を標準出力に表示します。Fprint
系関数: 指定されたio.Writer
に引数を表示します。Fprintln
系関数: 指定されたio.Writer
に引数を表示し、最後に改行を追加します。Fprintf
系関数: フォーマット文字列に基づいて指定されたio.Writer
に引数を表示します。Sprint
系関数: 引数を文字列にフォーマットして返します。Sprintln
系関数: 引数を文字列にフォーマットし、最後に改行を追加して返します。Sprintf
系関数: フォーマット文字列に基づいて引数を文字列にフォーマットして返します。
これらの関数は、Goプログラムでデバッグ出力、ログ記録、ユーザーへの情報表示など、幅広い用途で利用されます。
技術的詳細
このコミットの技術的な変更は非常にシンプルで、主にGo言語のソースコード全体にわたる一括置換です。具体的には、fmt
パッケージ内の以下の関数呼び出しが変更されています。
fmt.printf
->fmt.Printf
fmt.sprintf
->fmt.Sprintf
fmt.fprintf
->fmt.Fprintf
fmt.print
->fmt.Print
fmt.sprint
->fmt.Sprint
fmt.fprint
->fmt.Fprint
fmt.println
->fmt.Println
fmt.sprintln
->fmt.Sprintln
この変更は、fmt
パッケージの内部実装ファイルであるsrc/lib/fmt/print.go
において、これらの関数がexport
キーワードとともに定義されている箇所で、関数名自体が小文字から大文字に変更されています。そして、その関数を呼び出しているGo言語の様々なファイル(ドキュメントのサンプルコード、テストファイル、標準ライブラリの他の部分など)で、対応する関数呼び出しも一括で更新されています。
この種の変更は、コンパイラが新しい関数名を認識できるようにするために、コードベース全体で徹底的に行われる必要があります。もし一部の呼び出しが古い関数名のままであった場合、コンパイルエラーが発生します。
コアとなるコードの変更箇所
このコミットの核心的な変更は、src/lib/fmt/print.go
ファイルにあります。このファイルはfmt
パッケージの主要な実装を含んでおり、ここでprintf
などの関数が実際に定義されています。
--- a/src/lib/fmt/print.go
+++ b/src/lib/fmt/print.go
@@ -128,7 +128,7 @@ func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);
// These routines end in 'f' and take a format string.
-export func fprintf(w io.Write, format string, a ...) (n int, error *os.Error) {
+export func Fprintf(w io.Write, format string, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p := Printer();
p.doprintf(format, v);
@@ -136,12 +136,12 @@ export func fprintf(w io.Write, format string, a ...) (n int, error *os.Error) {
return n, error;
}
-export func printf(format string, v ...) (n int, errno *os.Error) {
- n, errno = fprintf(os.Stdout, format, v);
+export func Printf(format string, v ...) (n int, errno *os.Error) {
+ n, errno = Fprintf(os.Stdout, format, v);
return n, errno;
}
-export func sprintf(format string, a ...) string {
+export func Sprintf(format string, a ...) string {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p := Printer();
p.doprintf(format, v);
@@ -152,7 +152,7 @@ export func sprintf(format string, a ...) string {
// These routines do not take a format string and add spaces only
// when the operand on neither side is a string.
-export func fprint(w io.Write, a ...) (n int, error *os.Error) {
+export func Fprint(w io.Write, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p := Printer();
p.doprint(v, false, false);
@@ -160,12 +160,12 @@ export func fprint(w io.Write, a ...) (n int, error *os.Error) {
return n, error;
}
-export func print(v ...) (n int, errno *os.Error) {
- n, errno = fprint(os.Stdout, v);
+export func Print(v ...) (n int, errno *os.Error) {
+ n, errno = Fprint(os.Stdout, v);
return n, errno;
}
-export func sprint(a ...) string {
+export func Sprint(a ...) string {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p := Printer();
p.doprint(v, false, false);
@@ -177,7 +177,7 @@ export func sprint(a ...) string {
// always add spaces between operands, and add a newline
// after the last operand.
-export func fprintln(w io.Write, a ...) (n int, error *os.Error) {
+export func Fprintln(w io.Write, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p := Printer();
p.doprint(v, true, true);
@@ -185,12 +185,12 @@ export func fprintln(w io.Write, a ...) (n int, error *os.Error) {
return n, error;
}
-export func println(v ...) (n int, errno *os.Error) {
- n, errno = fprintln(os.Stdout, v);
+export func Println(v ...) (n int, errno *os.Error) {
+ n, errno = Fprintln(os.Stdout, v);
return n, errno;
}
-export func sprintln(a ...) string {
+export func Sprintln(a ...) string {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p := Printer();
p.doprint(v, true, true);
コアとなるコードの解説
上記のdiffは、fmt
パッケージ内でエクスポートされる関数群の定義が変更されたことを示しています。
export func fprintf(...)
がexport func Fprintf(...)
に変更されています。export func printf(...)
がexport func Printf(...)
に変更されています。export func sprintf(...)
がexport func Sprintf(...)
に変更されています。export func fprint(...)
がexport func Fprint(...)
に変更されています。export func print(...)
がexport func Print(...)
に変更されています。export func sprint(...)
がexport func Sprint(...)
に変更されています。export func fprintln(...)
がexport func Fprintln(...)
に変更されています。export func println(...)
がexport func Println(...)
に変更されています。export func sprintln(...)
がexport func Sprintln(...)
に変更されています。
これらの変更は、Go言語の命名規約に厳密に従うためのものです。export
キーワードは、これらの関数がパッケージの外部からアクセス可能であることを示しています。Goの慣習では、エクスポートされる識別子は常に大文字で始まるため、このコミットはGo言語のAPI設計の一貫性を保つ上で重要なステップでした。
この変更により、fmt
パッケージを利用するすべての既存のコードは、新しい大文字の関数名を使用するように更新される必要がありました。コミットの差分を見ると、doc/progs
以下のサンプルコードや、src/lib
以下の様々なテストファイルやライブラリファイルがこの変更の影響を受けていることがわかります。これは、Go言語の初期段階において、APIの安定化と標準化が進められていたことを示しています。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/
- Go言語のEffective Go - Naming: https://go.dev/doc/effective_go#names
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Go言語の
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt - Go言語のEffective Go: https://go.dev/doc/effective_go
- Go言語の命名規約に関する記事 (例: Qiita, Mediumなど、一般的なGo言語の命名規約に関する解説記事)
- Go言語の命名規則 - Qiita (例として挙げたものであり、実際の記事が存在するかは確認していません)
- Go言語の命名規則とベストプラクティス - Zenn (例として挙げたものであり、実際の記事が存在するかは確認していません)