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

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

このコミットは、Go言語の標準ライブラリにおけるfmtパッケージの関数名の変更を主に行っています。具体的には、printfsprintffprintfprintsprintfprintprintlnsprintlnといった関数が、それぞれPrintfSprintfFprintfPrintSprintFprintPrintlnSprintlnのように、先頭が大文字の形式に変更されています。これは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言語のprintfscanfに似た機能を提供し、様々なデータ型を文字列に変換したり、文字列からデータを解析したりする機能を持っています。

  • 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の安定化と標準化が進められていたことを示しています。

関連リンク

参考にした情報源リンク