nullable

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 8 Imported by: 0

README

nullable

import "github.com/brpaz/lib-go/nullable"

Package nullable provides a generic Value type that represents a value that may or may not be present — like [sql.NullString] but for any type T.

Constructing

Use Of to wrap a present value and Empty to represent absence:

name := nullable.Of("alice")      // valid, Val = "alice"
none := nullable.Empty[string]()  // invalid (null)

FromPtr converts from pointer-based APIs (generated DTOs, ORMs) where optional fields are represented as *T:

var p *string
n := nullable.FromPtr(p)  // invalid — p is nil
p  = ptr.Of("alice")
n  = nullable.FromPtr(p)  // valid, Val = "alice"
Reading

Value.Get returns the value and a boolean, similar to a map lookup:

if v, ok := name.Get(); ok {
    fmt.Println(v) // "alice"
}

Value.ValueOr is a one-liner with a fallback:

display := name.ValueOr("anonymous")

Value.ToPtr converts back to a pointer — nil when invalid — for round-tripping through pointer-based APIs:

p := name.ToPtr()  // *string pointing to "alice"

Value.String implements fmt.Stringer for logging and debugging:

fmt.Sprint(name)             // "alice"
fmt.Sprint(nullable.Empty[string]()) // "<null>"
Mutating
n.Set("bob")  // marks valid, sets Val
n.Clear()     // marks invalid, zeroes Val
JSON

Value marshals to the underlying JSON value when valid, or JSON null when not:

json.Marshal(nullable.Of("alice"))    // → "alice"
json.Marshal(nullable.Empty[string]()) // → null

var n nullable.Value[string]
json.Unmarshal([]byte(`"bob"`), &n) // n.Valid=true,  n.Val="bob"
json.Unmarshal([]byte(`null`),  &n) // n.Valid=false
Text encoding

Value implements encoding.TextMarshaler and encoding.TextUnmarshaler — an empty string round-trips as invalid (null), and any other value is formatted/parsed as text. This is what JSON map keys, [url.Values] and form/query encoders use for non-string and optional values. T must be a string, a basic numeric/bool kind, or implement the encoding.Text* interfaces itself; any other type returns an error:

nullable.Of(42).MarshalText()           // → []byte("42"), nil
nullable.Empty[int]().MarshalText()      // → []byte{}, nil

var n nullable.Value[int]
n.UnmarshalText([]byte("42")) // n.Valid=true, n.Val=42
n.UnmarshalText([]byte(""))   // n.Valid=false
SQL

Value implements [sql.Scanner] and [driver.Valuer] for use with database/sql:

var bio nullable.Value[string]
row.Scan(&bio) // NULL → bio.Valid=false; "x" → bio.Valid=true, bio.Val="x"

db.Exec("UPDATE users SET bio = ?", nullable.Of("new bio"))
db.Exec("UPDATE users SET bio = ?", nullable.Empty[string]()) // sends NULL
Equality

Equal compares two Values of a comparable T:

nullable.Equal(nullable.Of(5), nullable.Of(5))         // true
nullable.Equal(nullable.Empty[int](), nullable.Empty[int]()) // true — both invalid
nullable.Equal(nullable.Of(5), nullable.Empty[int]())  // false

Index

func Equal

func Equal[T comparable](a, b Value[T]) bool

Equal reports whether a and b represent the same optional value. Two invalid Values are equal; a valid and an invalid are not; two valid Values are equal when their underlying values are equal.

type Value

Value holds an optional value of type T.

type Value[T any] struct {
    Val   T
    Valid bool // true if Val is set
}

func Empty
func Empty[T any]() Value[T]

Empty returns an invalid (null) Value of type T.

func FromPtr
func FromPtr[T any](p *T) Value[T]

FromPtr converts a pointer to a Value. A nil pointer becomes an invalid (null) Value; a non-nil pointer becomes valid, wrapping a copy of the pointed-to value. Useful at boundaries with pointer-based APIs (generated DTOs, ORMs) that represent optional fields as *T.

func Of
func Of[T any](v T) Value[T]

Of returns a valid Value wrapping v.

func (*Value[T]) Clear
func (n *Value[T]) Clear()

Clear marks the Value as invalid/null.

func (Value[T]) Get
func (n Value[T]) Get() (T, bool)

Get returns (value, true) if valid, or (zero, false) if not.

func (Value[T]) IsNull
func (n Value[T]) IsNull() bool

IsNull returns true if the value is not valid.

func (Value[T]) MarshalJSON
func (n Value[T]) MarshalJSON() ([]byte, error)

MarshalJSON marshals to the JSON value if valid, or null if not.

func (Value[T]) MarshalText
func (n Value[T]) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. It returns an empty byte slice when invalid, or the textual representation of Val when valid — the form expected by JSON map keys, url.Values and form/query encoders. T must be a string, a basic numeric/bool kind, or implement encoding.TextMarshaler; any other type returns an error.

func (*Value[T]) Scan
func (n *Value[T]) Scan(src any) error

Scan implements sql.Scanner, allowing Value to be used as a scan destination. A nil src sets Valid=false; otherwise it delegates to sql.Scanner if T implements it, or falls back to reflect-based assignment, and sets Valid=true on success.

func (*Value[T]) Set
func (n *Value[T]) Set(v T)

Set sets the value and marks it valid.

func (Value[T]) String
func (n Value[T]) String() string

String implements fmt.Stringer, returning a textual representation of Val when valid, or "<null>" when not — useful for logging and debugging.

func (Value[T]) ToPtr
func (n Value[T]) ToPtr() *T

ToPtr converts n to a pointer. An invalid Value becomes nil; a valid Value becomes a pointer to a copy of Val. Pairs with FromPtr for round-tripping through pointer-based APIs.

func (*Value[T]) UnmarshalJSON
func (n *Value[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON parses JSON null as invalid, otherwise unmarshals into Val and sets Valid=true.

func (*Value[T]) UnmarshalText
func (n *Value[T]) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler. Empty input marks the Value as invalid (null); otherwise it parses the text into T. T must be a string, a basic numeric/bool kind, or *T must implement encoding.TextUnmarshaler; any other type returns an error.

func (Value[T]) Value
func (n Value[T]) Value() (driver.Value, error)

Value implements driver.Valuer, returning nil if not valid, or the underlying value if valid.

func (Value[T]) ValueOr
func (n Value[T]) ValueOr(fallback T) T

ValueOr returns the value if valid, otherwise fallback.

Generated by gomarkdoc

Documentation

Overview

Package nullable provides a generic Value type that represents a value that may or may not be present — like sql.NullString but for any type T.

Constructing

Use Of to wrap a present value and Empty to represent absence:

name := nullable.Of("alice")      // valid, Val = "alice"
none := nullable.Empty[string]()  // invalid (null)

FromPtr converts from pointer-based APIs (generated DTOs, ORMs) where optional fields are represented as *T:

var p *string
n := nullable.FromPtr(p)  // invalid — p is nil
p  = ptr.Of("alice")
n  = nullable.FromPtr(p)  // valid, Val = "alice"

Reading

Value.Get returns the value and a boolean, similar to a map lookup:

if v, ok := name.Get(); ok {
    fmt.Println(v) // "alice"
}

Value.ValueOr is a one-liner with a fallback:

display := name.ValueOr("anonymous")

Value.ToPtr converts back to a pointer — nil when invalid — for round-tripping through pointer-based APIs:

p := name.ToPtr()  // *string pointing to "alice"

Value.String implements fmt.Stringer for logging and debugging:

fmt.Sprint(name)             // "alice"
fmt.Sprint(nullable.Empty[string]()) // "<null>"

Mutating

n.Set("bob")  // marks valid, sets Val
n.Clear()     // marks invalid, zeroes Val

JSON

Value marshals to the underlying JSON value when valid, or JSON null when not:

json.Marshal(nullable.Of("alice"))    // → "alice"
json.Marshal(nullable.Empty[string]()) // → null

var n nullable.Value[string]
json.Unmarshal([]byte(`"bob"`), &n) // n.Valid=true,  n.Val="bob"
json.Unmarshal([]byte(`null`),  &n) // n.Valid=false

Text encoding

Value implements encoding.TextMarshaler and encoding.TextUnmarshaler — an empty string round-trips as invalid (null), and any other value is formatted/parsed as text. This is what JSON map keys, [url.Values] and form/query encoders use for non-string and optional values. T must be a string, a basic numeric/bool kind, or implement the encoding.Text* interfaces itself; any other type returns an error:

nullable.Of(42).MarshalText()           // → []byte("42"), nil
nullable.Empty[int]().MarshalText()      // → []byte{}, nil

var n nullable.Value[int]
n.UnmarshalText([]byte("42")) // n.Valid=true, n.Val=42
n.UnmarshalText([]byte(""))   // n.Valid=false

SQL

Value implements sql.Scanner and driver.Valuer for use with database/sql:

var bio nullable.Value[string]
row.Scan(&bio) // NULL → bio.Valid=false; "x" → bio.Valid=true, bio.Val="x"

db.Exec("UPDATE users SET bio = ?", nullable.Of("new bio"))
db.Exec("UPDATE users SET bio = ?", nullable.Empty[string]()) // sends NULL

Equality

Equal compares two Values of a comparable T:

nullable.Equal(nullable.Of(5), nullable.Of(5))         // true
nullable.Equal(nullable.Empty[int](), nullable.Empty[int]()) // true — both invalid
nullable.Equal(nullable.Of(5), nullable.Empty[int]())  // false

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Equal

func Equal[T comparable](a, b Value[T]) bool

Equal reports whether a and b represent the same optional value. Two invalid Values are equal; a valid and an invalid are not; two valid Values are equal when their underlying values are equal.

Types

type Value

type Value[T any] struct {
	Val   T
	Valid bool // true if Val is set
}

Value holds an optional value of type T.

func Empty

func Empty[T any]() Value[T]

Empty returns an invalid (null) Value of type T.

func FromPtr

func FromPtr[T any](p *T) Value[T]

FromPtr converts a pointer to a Value. A nil pointer becomes an invalid (null) Value; a non-nil pointer becomes valid, wrapping a copy of the pointed-to value. Useful at boundaries with pointer-based APIs (generated DTOs, ORMs) that represent optional fields as *T.

func Of

func Of[T any](v T) Value[T]

Of returns a valid Value wrapping v.

func (*Value[T]) Clear

func (n *Value[T]) Clear()

Clear marks the Value as invalid/null.

func (Value[T]) Get

func (n Value[T]) Get() (T, bool)

Get returns (value, true) if valid, or (zero, false) if not.

func (Value[T]) IsNull

func (n Value[T]) IsNull() bool

IsNull returns true if the value is not valid.

func (Value[T]) MarshalJSON

func (n Value[T]) MarshalJSON() ([]byte, error)

MarshalJSON marshals to the JSON value if valid, or null if not.

func (Value[T]) MarshalText

func (n Value[T]) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. It returns an empty byte slice when invalid, or the textual representation of Val when valid — the form expected by JSON map keys, url.Values and form/query encoders. T must be a string, a basic numeric/bool kind, or implement encoding.TextMarshaler; any other type returns an error.

func (*Value[T]) Scan

func (n *Value[T]) Scan(src any) error

Scan implements sql.Scanner, allowing Value to be used as a scan destination. A nil src sets Valid=false; otherwise it delegates to sql.Scanner if T implements it, or falls back to reflect-based assignment, and sets Valid=true on success.

func (*Value[T]) Set

func (n *Value[T]) Set(v T)

Set sets the value and marks it valid.

func (Value[T]) String

func (n Value[T]) String() string

String implements fmt.Stringer, returning a textual representation of Val when valid, or "<null>" when not — useful for logging and debugging.

func (Value[T]) ToPtr

func (n Value[T]) ToPtr() *T

ToPtr converts n to a pointer. An invalid Value becomes nil; a valid Value becomes a pointer to a copy of Val. Pairs with FromPtr for round-tripping through pointer-based APIs.

func (*Value[T]) UnmarshalJSON

func (n *Value[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON parses JSON null as invalid, otherwise unmarshals into Val and sets Valid=true.

func (*Value[T]) UnmarshalText

func (n *Value[T]) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler. Empty input marks the Value as invalid (null); otherwise it parses the text into T. T must be a string, a basic numeric/bool kind, or *T must implement encoding.TextUnmarshaler; any other type returns an error.

func (Value[T]) Value

func (n Value[T]) Value() (driver.Value, error)

Value implements driver.Valuer, returning nil if not valid, or the underlying value if valid.

func (Value[T]) ValueOr

func (n Value[T]) ValueOr(fallback T) T

ValueOr returns the value if valid, otherwise fallback.

Jump to

Keyboard shortcuts

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