モジュールのレッスン (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を構築します。
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 errorPrint と Println の違いは、*引数間のスペースと末尾の改行**のみです。 Println は常に \n を追加しますが、Print は追加しません。Printf は形式に従います。
主な動詞
| 動詞 | 何をするのか |
|---|---|
%v | デフォルト値 (実装されている場合は String() を呼び出します)。 |
%+v | フィールド名を含む構造体。 |
%#v | Go 構文 (デバッグとスナップショットに便利)。 |
%T | 値の動的タイプ。 |
%d | 10 進数の整数。 |
%b %o %x %X | 2進数、8進数、16進数(小文字/大文字)。 |
%f %e %g | 浮動小数点: 固定、指数関数、コンパクト。 |
%s | 文字列 (または error/Stringer)。 |
%q | Go スタイルの 引用符で囲まれた文字列 (エスケープを含む)。 |
%c | Unicode 文字 (rune)。 |
%p | 16 進数のポインター。 |
%w | エラーラップ (Errorf 内のみ)。 |
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。
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 はそれを実行できます。
if _, err := os.Open(path); err != nil {
return fmt.Errorf("read config %q: %w", path, err)
}%w の代わりに %v を使用すると、エラー メッセージが 出力されますが、チェーンは切断されます。アンラップも errors.Is もありません。ルール: 呼び出し元がエラーのタイプまたは ID を区別できるようにしたい場合は、%w を使用します (Errorf ごとに 1 つだけ)。
演習
fmt.Sprintf を使用して、整数 42 から文字列 '[42]' をフォーマットし、出力します。
3 回の試行後に解決策が利用可能になります
動詞 %+v を使用して構造体 p を出力します (フィールド名を含める必要があります)。
3 回の試行後に解決策が利用可能になります
fmt.Errorf で使用される動詞は、errors.Is/As のエラー チェーンを保持するものはどれですか?
err := fmt.Errorf("read %q: ???", path, base)