メインコンテンツにスキップ
モジュール 8 · レッスン 1 / 5コース内の 36/50~10 min
モジュールのレッスン (1/5)

高度な「fmt」

fmt パッケージは、Go のすべてのテキスト I/O へのゲートウェイです。これをよく理解するということは、外部ライブラリに頼らずに、読み取り可能なログ、有益なエラーを書き、慣用的に値をフォーマットすることを意味します。

四家族

fmt は、接頭辞によって区別される 4 つのファミリーの関数を公開します。

  • Print* → os.Stdout (Print、Println、Printf) に書き込みます。
  • Fprint* → 任意の io.Writer (Fprintln(os.Stderr, ...)、Fprintf(file, ...)) に書き込みます。
  • Sprint* → 印刷せずに 文字列 を返します (Sprintf、Sprintln)。
  • Errorf → フォーマットされた error を構築します。
Go
fmt.Println("hello")                       // stdout
fmt.Fprintln(os.Stderr, "boom")            // stderr
s := fmt.Sprintf("[%d]", 42)               // "[42]"
err := fmt.Errorf("parse %q: %w", in, base) // wrapped error

Print と Println の違いは、*引数間のスペースと末尾の改行**のみです。 Println は常に \n を追加しますが、Print は追加しません。Printf は形式に従います。

主な動詞

動詞何をするのか
%vデフォルト値 (実装されている場合は String() を呼び出します)。
%+vフィールド名を含む構造体。
%#vGo 構文 (デバッグとスナップショットに便利)。
%T値の動的タイプ。
%d10 進数の整数。
%b %o %x %X2進数、8進数、16進数(小文字/大文字)。
%f %e %g浮動小数点: 固定、指数関数、コンパクト。
%s文字列 (または error/Stringer)。
%qGo スタイルの 引用符で囲まれた文字列 (エスケープを含む)。
%cUnicode 文字 (rune)。
%p16 進数のポインター。
%wエラーラップ (Errorf 内のみ)。
Go
type Point struct{ X, Y int }
p := Point{1, 2}
fmt.Printf("%v\n", p)   // {1 2}
fmt.Printf("%+v\n", p)  // {X:1 Y:2}
fmt.Printf("%#v\n", p)  // main.Point{X:1, Y:2}
fmt.Printf("%T\n", p)   // main.Point

幅、精度、フラグ

数値動詞と文字列動詞は 幅 と 精度 を受け入れます。

  • %6d → 最小幅 6、左にスペースが埋め込まれます。
  • %-6d → 幅 6、右パディング (フラグ -)。
  • %06d → 幅 6、0 (フラグ 0) でパディング。
  • %.2f → 精度 10 進数 2 桁。
  • %8.2f → 幅 8、精度 2。
Go
fmt.Printf("|%6d|\n", 42)    // |    42|
fmt.Printf("|%-6d|\n", 42)   // |42    |
fmt.Printf("|%06d|\n", 42)   // |000042|
fmt.Printf("|%8.2f|\n", 3.14)// |    3.14|

整列されたテーブルの場合、text/tabwriter に移行する前の、テキスト列の固定幅 + %-...s が最も単純なパターンです。

%w とエラー ラッピング

%w は特別です。fmt.Errorf__ 内でのみ機能し、チェーン内の元のエラーを保存するため、errors.Is および errors.As はそれを実行できます。

Go
if _, err := os.Open(path); err != nil {
    return fmt.Errorf("read config %q: %w", path, err)
}

%w の代わりに %v を使用すると、エラー メッセージが 出力されますが、チェーンは切断されます。アンラップも errors.Is もありません。ルール: 呼び出し元がエラーのタイプまたは ID を区別できるようにしたい場合は、%w を使用します (Errorf ごとに 1 つだけ)。

演習

運動#go.m8.l1.e1
試行回数: 0読み込み中…

fmt.Sprintf を使用して、整数 42 から文字列 '[42]' をフォーマットし、出力します。

エディターを読み込み中…

3 回の試行後に解決策が利用可能になります

運動#go.m8.l1.e2
試行回数: 0読み込み中…

動詞 %+v を使用して構造体 p を出力します (フィールド名を含める必要があります)。

エディターを読み込み中…

3 回の試行後に解決策が利用可能になります

Quiz#go.m8.l1.e3
準備完了

fmt.Errorf で使用される動詞は、errors.Is/As のエラー チェーンを保持するものはどれですか?

Go
err := fmt.Errorf("read %q: ???", path, base)
回答の選択肢