must

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2026 License: MIT Imports: 2 Imported by: 0

README

must: panic-on-error for invariants

Convert fallible operations to panics when errors indicate bugs, not runtime conditions. If you're tempted to ignore an error with _ =, use must instead.

An invariant is a precondition that, if violated, means the program has a bug—not a runtime error to handle.

db := must.Get(sql.Open("postgres", dsn))
must.BeNil(db.Ping())

See pkg.go.dev for complete API documentation.

Quick Start

import "github.com/binaryphile/fluentfp/must"

// Extract value or panic
db := must.Get(sql.Open("postgres", dsn))

// Panic if error non-nil
must.BeNil(db.Ping())

// Environment variable or panic
home := must.Getenv("HOME")

// Wrap fallible func for HOF use
mustAtoi := must.Of(strconv.Atoi)
ints := slice.From(strings).ToInt(mustAtoi)

API Reference

Function Signature Purpose Example
Get Get[T](t T, err error) T Value or panic must.Get(os.Open(path))
Get2 Get2[T,T2](t T, t2 T2, err error) (T, T2) Two-value variant must.Get2(fn())
BeNil BeNil(err error) Panic if non-nil must.BeNil(db.Ping())
Getenv Getenv(key string) string Env var or panic must.Getenv("HOME")
Of Of[T,R](fn func(T)(R,error)) func(T)R Wrap for HOF use must.Of(strconv.Atoi)

Naming Convention

When storing a must-wrapped function in a variable, prefix with must to signal panic behavior:

mustAtoi := must.Of(strconv.Atoi)
ints := slice.From(strings).ToInt(mustAtoi)

This makes panic behavior visible at the call site.

For more naming patterns, see Naming Functions for Higher-Order Functions.

Recovering from Panics

When using must.Of in pipelines, panics can be caught with defer/recover:

func SafeParseAll(inputs []string) (results []int, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("parse failed: %v", r)
        }
    }()

    mustAtoi := must.Of(strconv.Atoi)
    results = slice.From(inputs).ToInt(mustAtoi)
    return results, nil
}

This pattern converts pipeline panics back to errors at the boundary. Use it when:

  • Processing untrusted input that may contain invalid values
  • You want FP-style pipelines but need error handling at the edges
  • The calling code expects errors, not panics

Patterns

Initialization Sequences

Use must.Get and must.BeNil together for init/setup code where errors are fatal:

func OpenDatabase(cfg Config) *Database {
    db := must.Get(sql.Open("postgres", cfg.DSN))
    must.BeNil(db.Ping())

    db.SetMaxIdleConns(cfg.IdleConns)
    db.SetMaxOpenConns(cfg.OpenConns)

    return &Database{db: db}
}
Config Loading

Combine with config parsing where missing config is fatal:

func LoadConfig() Config {
    var config Config
    must.BeNil(viper.ReadInConfig())
    must.BeNil(viper.Unmarshal(&config))
    return config
}
Embedding Files

Use with embed.FS when embedded files must exist:

//go:embed README.md
var files embed.FS

func GetReadme() string {
    return string(must.Get(files.ReadFile("README.md")))
}
Other Common Uses
// Time parsing with known-valid formats
timestamp := must.Get(time.Parse("2006-01-02 15:04:05", s.ScannedAt))

// Validation-only (discard result)
_ = must.Get(strconv.Atoi(configID))  // panics if invalid

When NOT to Use must

  • Recoverable errors — If the caller can handle it, return error
  • User input — Never panic on external input; validate and return errors
  • Library code — Libraries should return errors, not panic
  • Production request handlers — One bad request shouldn't crash the server
  • Expected failures — Network timeouts, file not found, etc. are expected; handle them

Never Ignore Errors

When you write _ = doSomething(), you're implicitly declaring an invariant: "this won't error." But what if it does?

_ = os.Setenv("PATH", newPath)  // Silent failure, program continues corrupted

The program continues in an invalid state. You've traded a clear failure for silent corruption.

must makes the invariant explicit:

must.BeNil(os.Setenv("PATH", newPath))  // Invariant enforced, clear failure

Every _ = fn() that discards an error should be must.BeNil() or must.Get(). If you're confident the error "won't happen," prove it—by panicking if it does.

Tools like errcheck flag ignored errors as bugs.

See Also

For typed error handling without panics, see either.

Documentation

Overview

Package must provides functions to panic if a condition is not met.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BeNil

func BeNil(err error)

BeNil panics if err is not nil.

func Get

func Get[T any](t T, err error) T

Get returns the value of a (value, error) pair of arguments unless error is non-nil. In that case, it panics.

func Get2

func Get2[T, T2 any](t T, t2 T2, err error) (T, T2)

Get2 returns the value of a (value, value, error) set of arguments unless error is non-nil. In that case, it panics.

func Getenv

func Getenv(key string) string

Getenv returns the value in the environment variable named by key. It panics if the environment variable doesn't exist or is empty.

func Of

func Of[T, R any](fn func(T) (R, error)) func(T) R

Of returns the "must" version of fn. fn must be a single-argument function.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL