package opt // Coalesce returns the first non-empty Opt. // If all Opt values are empty, it returns empty Opt. func Coalesce[T any](opts ...Opt[T]) (r Opt[T]) { for _, o := range opts { if o.IsPresent() { return o } } return } // Else returns the value from the first non-empty Opt. // If all Opt values are empty, it returns the final value. func Else[T any](final T, opts ...Opt[T]) T { for _, o := range opts { if val, ok := o.Get(); ok { return val } } return final }
package opt // Of creates a new Opt with the given value and ok set to true. func Of[T any](val T) Opt[T] { return Opt[T]{val: val, ok: true} } // FromOk creates a new Opt with the given value and ok status. func FromOk[T any](val T, ok bool) Opt[T] { return Opt[T]{val: val, ok: ok} } // FromErr creates a new Opt from a value and an error. // - If the error is nil, it returns an Opt with the value and ok set to true. // - If the error is not nil, it returns an empty Opt. func FromErr[T any](val T, err error) (o Opt[T]) { if err == nil { return Opt[T]{val: val, ok: true} } return // zero opt is valid empty opt } // FromPtr creates a new Opt from a pointer. // - If the pointer is not nil, it returns an Opt with the value pointed to and ok set to true. // - If the pointer is nil, it returns an empty Opt. func FromPtr[T any](ptr *T) (o Opt[T]) { if ptr != nil { return Opt[T]{val: *ptr, ok: true} } return // zero opt is valid empty opt } // FromZero creates a new Opt from a zeroable (emptiable) value. // - If the value is not equal to its zero value, it returns an Opt with the value and ok set to true. // - If the value is equal to its zero value, it returns an empty Opt. func FromZero[T comparable](v T) (o Opt[T]) { var zero T if v != zero { return Opt[T]{val: v, ok: true} } return // zero opt is valid empty opt }
// Package opt provides a generic optional type Opt // that can be used to represent a value that may or may not be present. package opt // Opt is a generic optional type that can hold a value of type T or be empty. type Opt[T any] struct { val T ok bool } // IsPresent returns true if the Opt contains a value. func (o Opt[T]) IsPresent() bool { return o.ok } // IsMissing returns true if the Opt does not contain a value. func (o Opt[T]) IsMissing() bool { return !o.ok } // Get returns the value and a boolean indicating if the value is present. func (o Opt[T]) Get() (T, bool) { return o.val, o.ok } // Ptr returns a pointer to the value if it is present, or nil if it is not. func (o Opt[T]) Ptr() *T { if !o.ok { return nil } return &o.val } // Or returns the value if it is present, otherwise it returns the provided fallback value. func (o Opt[T]) Or(fallback T) T { if o.ok { return o.val } return fallback } // OrZero returns the value if it is present, otherwise it returns the zero value of T. func (o Opt[T]) OrZero() T { if o.ok { return o.val } var zero T return zero }
package ptr import "github.com/sr9000/go-ptr-tools/ref" // Coalesce returns the first not nil pointer. // If all pointers are nil, it returns nil. func Coalesce[T any](pointers ...*T) *T { for _, ptr := range pointers { if ptr != nil { return ptr } } return nil } // Else returns the first not nil pointer as a ref.Ref. // If all pointers are nil, it returns the final ref.Ref. func Else[T any](final ref.Ref[T], pointers ...*T) ref.Ref[T] { for _, ptr := range pointers { if ptr != nil { return ref.Guaranteed(ptr) } } return final }
// Package ptr provides several helper routines for working with pointers. package ptr // Of returns pointer onto a value, works with primitive types (int, string, etc.). func Of[T any](v T) *T { return &v } // FromOk creates a new pointer from a value and an ok flag. // If ok equals true, it returns a pointer to val, else nil. func FromOk[T any](val T, ok bool) *T { if ok { return &val } return nil } // FromErr creates a new pointer from a value and an error. // - If the error is nil, it returns a pointer to val. // - If the error is not nil, it returns nil. func FromErr[T any](val T, err error) *T { if err == nil { return &val } return nil } // FromZero creates a new pointer from a zeroable (emptiable) value. // - If the value is not equal to its zero value, it returns a pointer to val. // - If the value is equal to its zero value, it returns nil. func FromZero[T comparable](v T) *T { var zero T if v != zero { return &v } return nil } // OrVal returns the value pointed to by ptr if it is not nil, otherwise it returns the provided value. func OrVal[T any](value T, ptrs ...*T) T { for _, p := range ptrs { if p != nil { return *p } } return value } // OrZero returns the value pointed to by ptr if it is not nil, otherwise it returns the zero value of T. func OrZero[T any](ptrs ...*T) T { var zero T return OrVal(zero, ptrs...) }
package ref // Of returns a new Ref based on the given value. func Of[T any](v T) Ref[T] { return Ref[T]{&v} } // Guaranteed returns a new Ref based on the given pointer that is guaranteed to be not nil. // It is useful when you know that the pointer is not nil, but the compiler does not. func Guaranteed[T any](notNilPtr *T) Ref[T] { return Ref[T]{notNilPtr} } // FromPtr returns a new Ref based on the given pointer. // It returns an error if the pointer is nil. func FromPtr[T any](ptr *T) (Ref[T], error) { if ptr == nil { return Ref[T]{}, ErrPtrMustBeNotNil } return Ref[T]{ptr}, nil }
// Package ref provides a reference type Ref that can be used to store an "always valid pointer". package ref // Ref must be used as mental anchor for "always valid pointer" guarantees. type Ref[T any] struct { ptr *T } // Ptr returns the pointer to the value. // There is no need to check for nil, because the pointer is guaranteed to be not nil. func (r Ref[T]) Ptr() *T { return r.ptr } // Val returns the value itself. func (r Ref[T]) Val() T { return *r.ptr }