こんにちは、kurumi-bioです。
2023年2月1日にGo言語のメジャーバージョンアップが行われてバージョンが1.20になりました。
今まで学習してきたfmtパッケージにも変更がありましたので調査しました。
環境
OSバージョン:Windows11 Home 22H2
Go言語のバージョン:
fmtパッケージの変更点
- Errorf 関数は、%w 形式の動詞の複数回の出現をサポートし、%w へのすべての引数のリストにアンラップするエラーを返します。
- 新しい FormatString 関数は、State に対応するフォーマット ディレクティブを復元します。これは Formatter で役立ちます。実装。
fmt.Errorf
func Errorf(format string, a ...any) error
Version: go1.19.4の説明
Errorf は、フォーマット指定子に従ってフォーマットし、エラーを満たす値として文字列を返します。
フォーマット指定子にエラー オペランドを持つ %w 動詞が含まれている場合、返されるエラーは、オペランドを返す Unwrap メソッドを実装します。複数の %w 動詞を含めたり、エラー インターフェイスを実装しないオペランドを指定したりすることは無効です。それ以外の場合、%w 動詞は %v の同義語です。
Version: go1.20の説明
Errorf は、フォーマット指定子に従ってフォーマットし、エラーを満たす値として文字列を返します。
フォーマット指定子にエラー オペランドを持つ %w 動詞が含まれている場合、返されるエラーは、オペランドを返す Unwrap メソッドを実装します。複数の %w 動詞がある場合、返されるエラーは Unwrap メソッドを実装し、引数に現れる順序ですべての %w オペランドを含む [] エラーを返します。エラー インターフェイスを実装しないオペランドを %w 動詞に指定することは無効です。それ以外の場合、%w 動詞は %v の同義語です。
説明が異なる箇所に色を付けました。
異なる点はgo1.19.4では複数の%wを使うことが禁止されていましたが、go1.20では、複数の%wの記載が可能となっています。
では、fmt.Errorf
に2つの%wを指定すると、どうなるか試してみました。
<サンプルコード>ErrorfTest.go
package main import ( "fmt" "errors" ) func main() { e1 := errors.New("error1") e2 := errors.New("error2") e := fmt.Errorf("%w %w", e1, e2) fmt.Println(e) }
<実行結果>
go1.19.4では、二つ目の%wが表示されませんでしたが、
go1.20ですと、書式指定した通りに2つのerrorが表示されました。
<広告の下に記事が続きます。>
fmt.FormatString
func FormatString(state State, verb rune) string
FormatString は、State によってキャプチャされた完全修飾フォーマット ディレクティブを表す文字列を返し、その後に引数動詞が続きます。 (状態自体には動詞は含まれません。) 結果には先頭のパーセント記号があり、その後にフラグ、幅、および精度が続きます。欠落しているフラグ、幅、および精度は省略されています。この関数を使用すると、Formatter は、Format の呼び出しをトリガーする元のディレクティブを再構築できます。
go1.20で新規追加された関数です。
fmt.Stateがinterfaceで宣言されていて、これで正しいのかわからないのですが、
4桁の数値の書式設定を返すサンプルコードを作成しました。
<サンプルコード>FormatStringTest.go
package main import ( "fmt" "errors" ) type FourDigit struct {} func (f FourDigit) Write(b []byte)(int, error) { e := errors.New("Write error!") return 0, e } func (f FourDigit) Width()(int, bool){ return 4, true } func (f FourDigit) Precision()(int ,bool){ return 0, false } func (f FourDigit) Flag(c int) bool{ return true } func main() { var f FourDigit var s fmt.State var v rune v = 'd' s = f fmt.Println(fmt.FormatString(s,v)) fmt.Printf(fmt.FormatString(s,v),4) }
<実行結果>
それっぽい書式設定文字列が返されて、fmt.Printfに渡すことができました。 こんな遠回りなことをしなくても、もっと簡単にできそうな気がしますので、 根本的に使い方が間違っている気がしました。
ちなみに、go1.19.4では「未定義」と表示されて実行不可でした。
最後までご覧いただきありがとうございます