Nullable & Optional Values
The nulls and optional packages model fields that can be absent — typed
alternatives to raw pointers and to sql.Null*.
nulls.Null[T]
nulls.Null[T] wraps any type T with a Valid flag and interoperates with
JSON, database/sql, and database/sql/driver:
type Null[T any] struct {
V T
Valid bool
}var _ json.Marshaler = Null[int]{}
var _ json.Unmarshaler = (*Null[int])(nil)
var _ sql.Scanner = (*Null[int])(nil)
var _ driver.Valuer = Null[int]{}New(v) builds a valid value. In JSON, an invalid Null marshals to null
and a JSON null unmarshals to an invalid instance; non-null values
marshal/unmarshal as the wrapped type — including time values, slices, pointers,
and structs. Through sql, Scan(nil) clears the value and Value() produces
nil for an invalid instance, so nullable database columns round-trip without
special handling:
type User struct {
ID int64 `db:"id"`
AvatarURL nulls.Null[string] `db:"avatar_url"`
}optional.Option[T]
optional.Option[T] is the same idea as a plain value with a presence flag, and
Some(v)/None[T]() build it:
type Option[T any] struct {
Value T
Valid bool
}opt := optional.Some("pending")
// or
opt := optional.None[string]()
if opt.Valid {
// ...
}Note that the optional package is still a stub: its MarshalJSON,
UnmarshalJSON, and text/binary encoding methods currently panic. Use
nulls.Null[T] when a nullable value must cross a JSON or database boundary.