🎁
なんでもMust化するgo-mustモジュール作った
goには、Must関数と呼ばれる慣習があります。
例えば、regexp.MustCompileは正規表現のコンパイルを行いますが、コンパイルに失敗するとpanicを発生させます。パッケージスコープ変数やinit関数の中で使われることが多いです。他にも text/template.Must関数なども同じ思想で設計された関数です。
var (
re1, _ = regexp.Compile(`(\w+)`)
re2 = regexp.MustCompile(`(\w+)`)
)
var t = template.Must(template.New("name").Parse("text"))
このような標準パッケージの関数に倣って、テスト用のユーティリティ関数としてMust関数を用意している人はいるではないでしょうか。例えば、time.Parseをラッピングしたtimeutil.MustParse()を用意するなどです。
var (
t1, _ := time.Parse(time.RFC3339, "2020-01-01T10:00:00Z")
t2 := timeutil.MustParse(time.RFC3339, "2020-01-01T10:00:00Z")
)
func MustParse(layout, value string) time.Time {
t, err := time.Parse(layout, value)
if err != nil {
panic(err)
}
return t
}
Must系関数は、元の関数を呼んでerrorを受け取りnilでなければpanicを起こすような関数を定義すればよいだけなので、比較的容易に定義できます。ですが、Must化したい関数の数だけ新たに定義するのは面倒です。
そこで、汎用的にMust化できるようなモジュールを作ってみました。
tm := must.Get2(time.Parse(time.RFC3339, "2020-01-01T00:00:00Z"))
v, n := must.Get3(big.ParseFloat("1.2345678", 10, 1000, big.ToNearestEven))
Get2, Get3, Get4, ..., Get7 という関数を用意しています。数字は対象の関数の引数の数に対応しています。
コードを見れば仕組みは単純で、genericsで任意の型を受け入れて、errorをハンドリングした後にerror以外の返り値を返却しているだけです。
ユニットテストを書くのが少し便利になりました。
Discussion