$30 off During Our Annual Pro Sale. View Details »

fmfm🤔 fmtパッケージ - tenntenn.go#4

fmfm🤔 fmtパッケージ - tenntenn.go#4

この資料はtenntenn.go#4で登壇を行った際に用いた資料です。

■ tenntenn.goとは
tenntenn.goはtenntennが主催し、そしてすべてのセッションがtenntennによる登壇のGoに関する勉強会です。

イベントページ:https://tenntenn.connpass.com/event/240858/
ハッシュタグ:#tenngo
資料(Googleスライド):https://tenn.in/fmt
動画:https://tenn.in/fmt-video

■ 登壇者&主催者

・名前:tenntenn / 上田拓也
・HP:https://tenntenn.dev
・Twitter:https://twitter.com/tenntenn

メルカリ/メルペイ所属。バックエンドエンジニアとして日々Goを書いている。Google Developer Expert (Go)。一般社団法人Gophers Japan代表。Go Conference主催者。大学時代にGoに出会い、それ以来のめり込む。人類をGopherにしたいと考え、Goの普及に取り組んでいる。複数社でGoに関する技術アドバイザーをしている。マスコットのGopherの絵を描くのも好き。

■ お仕事の依頼について

副業にて技術顧問やアドバイザーなどを行っています。過去の実績や問い合わせフォームは以下のURLからご確認ください。
https://tenntenn.dev/ja/job/

#golang #tenntenn #tenngo #Go言語

tenntenn - Takuya Ueda
PRO

March 05, 2022
Tweet

More Decks by tenntenn - Takuya Ueda

Other Decks in Technology

Transcript

  1. The Go gopher was designed by Renée French. The gopher

    stickers was made by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license. fmfm🤔 fmtパッケージ 2022年03月05日(金) 資料:https://tenn.in/fmt
  2. 上田拓也 Go ビギナーズ
 Go Conference
 @tenntenn tenntenn.dev Google Developer Expert

    (Go) 一般社団法人 Gophers Japan 代表理事 Experts Team
  3. fmtパッケージとは? ▪ 書式に関する処理をまとめたパッケージ • https://pkg.go.dev/fmt • Print系の関数:表示を行う関数 ◦ F◯◯系:出力先をio.Writerインタフェースとして指定できる ◦

    S◯◯系:文字列として出力する ◦ ◯◯f系:出力の書式を指定できる ◦ ◯◯ln系:末尾に改行をつける • Scan系の関数:入力を行う関数 ◦ F◯◯系:入力元をio.Readerインタフェースとして指定できる ◦ S◯◯系:文字列から入力を得る ◦ ◯◯f系:入力の書式を指定できる ◦ ◯◯ln系:改行区切りで入力を受け付ける
  4. 便利なverb ▪ 書式を指定する文字(rune型) • 指定する値の型によって挙動は変わる • 基本はCのprintf関数のverbに良く似ている verb 意味 使い方

    v その型のデフォルトの書式を用いる fmt.Printf("%v", "hoge") // hoge q 文字や文字列をクォートで囲む fmt.Printf("%q", "hoge") // "hoge" T Goの型を表す fmt.Printf("%T", "hoge") // string p ポインタ fmt.Printf("%p", &x)
  5. 書式のフラグ ▪ 書式に付加情報を指定する • 無効なフラグを指定すると無視される • int型で表される(rune型ではない) flag 意味 使い方

    + 数値の場合は必ず+符号をつける。構造体の 場合はフィールド名をつける fmt.Printf("%v", "hoge") // hoge - 左詰め fmt.Printf("%-2d@", 1) // 1 @ # その書式のより詳しい形式。 %#vはGoの構文 上の表現になる fmt.Printf("%#v", []int{1}) // []int{1} ' ' 空白。%dは省略された符号のためのスペー ス fmt.Printf("% d", 100) // 100 0 ゼロ埋めする fmt.Printf("%02d", 1) // 01
  6. 幅と精度 ▪ 幅(width)はverbの前に数値で記述 ▪ 精度(precision)は幅の後ろの.に数値で記述 書式 幅 精度 %f デフォルト

    デフォルト %9f 9 デフォルト %.2f デフォルト 2 %9.2f 9 2 %9.f 9 0 fmt.Printf("%9.2f", 12.345) // 12.35
  7. インデックスを指定して書式を適用 ▪ verbの前に[n]を指定する • 関数のn番目の引数に対して書式を指定する • 同じ値に複数の書式を指定したい場合に用いると便利 fmt.Printf("%[2]d %[1]d\n", 10,

    20) // 20 10 fmt.Printf("%[1]v %[1]T\n", 10) // 10 int
  8. 文字列のクォート ▪ %qを指定する • %#qはstrconv.CanBackquote関数がtrueを返す場合は``で括る • strconv.Quote関数でもOK • 逆をやりたい場合はstrconv.Unquote関数を用いる fmt.Printf("%q\n",

    "hoge") // "hoge" fmt.Printf("%#q %#q\n", "hoge", "`hoge`") // `hoge` "`hoge`" s := strconv.Quote(`"hoge"`) fmt.Println(s) // "\"hoge\"" fmt.Println(strconv.Unquote(s)) // "hoge" <nil>
  9. fmtパッケージのインタフェース ▪ Print系のインタフェース • Stringerインタフェース • GoStringerインタフェース • Formatterインタフェース •

    Stateインタフェース ▪ Scan系のインタフェース • Scannerインタフェース • ScanStateインタフェース
  10. fmt.Stringerインタフェース ▪ その型のネイティブなフォーマットを定義する • 書式を指定しないPrint系の関数で呼ばれる ◦ Printf系でも%sなどの書式を指定すると呼ばれる type Stringer interface

    { String() string }
  11. fmt.GoStringerインタフェース ▪ 書式で%#vを指定された場合の文字列を返す type GoStringer interface { GoString() string }

  12. fmt.Formatterインタフェース ▪ 書式に対する振る舞いを定義するインタフェース • verbやフラグ、精度、幅などを自由に定義できる • verbはrune型で表される • 文字列の書き込みやフラグ、精度、幅はStateインタフェースが担当 type

    Formatter interface { Format(f State, verb rune) } 参考:fmt.Formatterを実装して%vや%+vをカスタマイズしたり、 %3🍺みたいな書式をつくってみよう
  13. fmt.Stateインタフェース ▪ 1つのverbに対する処理を記述する • 幅、精度、フラグが取得できる ◦ すべてint型で表される • Writeメソッドを使って書き込む ◦

    Fprint系の関数にも対応 type State interface { // フォーマットした結果を書き込む Write(b []byte) (n int, err error) // 幅を取得、設定されていない場合は okがfalse Width() (wid int, ok bool) // 精度を取得、設定されていない場合は okがfalse Precision() (prec int, ok bool) // フラグが指定されているか取得 Flag(c int) bool }
  14. fmt.Scannerインタフェース ▪ Scan系の書式の振る舞いを記述する • fmt.Scan関数やfmt.Scanln関数の場合はverbはvになる type Scanner interface { Scan(state

    ScanState, verb rune) error }
  15. fmt.ScanStateインタフェース ▪ トークンごとに読み込みを行う • 幅なども取れる type ScanState interface { //

    1コードポイントを読み込む ReadRune() (r rune, size int, err error) // 次のReadRuneでも同じ結果が返ってくるようにする UnreadRune() error // 空白を飛ばす SkipSpace() // skipSpaceがtrueの場合は空白を飛ばす。 fがtrueを返す間読み込む Token(skipSpace bool, f func(rune) bool) (token []byte, err error) // 幅を取得、設定されていない場合は okがfalse Width() (wid int, ok bool) // ReadRuneがあるため常にエラーを返すように実装する Read(buf []byte) (n int, err error) }
  16. fmt.Errorf関数で作られるエラー ▪ ラップしない場合 • 書式を指定してエラーを作成 • errors.New関数では作成できない複雑なエラーメッセージのエラー ▪ ラップする場合 •

    %wを指定する • 引数で指定したエラーをラップしてエラーを作る • Unwrapメソッドを実装したエラーが作られる • errors.Unwrap関数で元のエラーが取得できる err := fmt.Errorf("%s is not found", name) err := fmt.Errorf("bar: %w", errors.New("foo")) fmt.Println(err) // bar: foo fmt.Println(errors.Unwrap(err)) // foo
  17. まとめ ▪ 案外知らないことが多い • パッケージドキュメントを読みましょう ▪ インタフェースを上手く使おう • StringメソッドとGoStringメソッドを使い分ける •

    Formatterインタフェースを実装する