go / must

I use must helpers to simplify initialization code where errors indicate programmer mistakes, not runtime conditions.

The pattern

package must

// Do panics if err is non-nil.
func Do(err error) {
	if err != nil {
		panic(err)
	}
}

// Get returns v as-is. It panics if err is non-nil.
func Get[T any](v T, err error) T {
	if err != nil {
		panic(err)
	}
	return v
}

Usage

Package-level initialization where errors are bugs:

var (
	homeDir  = must.Get(os.UserHomeDir())
	configRe = must.Get(regexp.Compile(`^[a-z]+$`))
	baseURL  = must.Get(url.Parse("https://api.example.com"))
)

Cleanup where errors are unexpected:

defer must.Do(f.Close())
defer must.Do(rows.Close())

When to use

Use must when:

Don't use must when:

Comparison

Without must:

re, err := regexp.Compile(`^[a-z]+$`)
if err != nil {
	panic(err) // or log.Fatal
}

With must:

re := must.Get(regexp.Compile(`^[a-z]+$`))

The intent is clearer: this must succeed or the program is broken.

← All articles