🎁

なんでもMust化するgo-mustモジュール作った

2024/08/15に公開

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化できるようなモジュールを作ってみました。

https://github.com/uechoco/go-must

https://pkg.go.dev/github.com/uechoco/go-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以外の返り値を返却しているだけです。

https://github.com/uechoco/go-must/blob/main/must.go

ユニットテストを書くのが少し便利になりました。

Discussion