Optional types for Go — generic-first SQL+JSON nullable types
Option[T]— generic foundation onsql.Null[T]with JSON/SQL/Text support- 9 concrete types — String, Int, Int32, Int16, Float, Bool, Byte, Time
Field[T]— three-state (absent/null/value) for PATCH APIOrNull[T]constructors — zero value → null mapping (eliminates boilerplate)FieldFromOption[T]— lossless Option→Field conversion for PATCH workflows- Functional API — Map, FlatMap, Equal
zero/subpackage — alternative semantics (zero value = null)internal/— shared unmarshal helpers (DRY)- Compile-time interface checks — driver.Valuer, sql.Scanner, json.Marshaler on all types
- 82% coverage (opt), 62% coverage (zero)
- Zero-allocation unmarshal, Bool marshal <1ns
- CI: 3 OS × 3 Go versions, Codecov OIDC
- json/v2 compatible
- driver.Valuer verified on all 16 concrete types
- Coverage 90%+ on both opt and zero
- Edge case tests: concurrent access, large values, unicode
-
Uint/Uint64types -
JSONtype (raw JSON storage,json.RawMessagewrapper) -
Bytestype ([]bytefor JSONB/binary columns) -
Field.ApplyTo(current Option[T]) Option[T]— PATCH merge
-
OrElseon concrete types (not just Option[T]) -
Filter(func(T) bool) Option[T]— keep value only if predicate matches - pgx native type support (beyond sql.Scanner)
- sqlx
NamedExec/StructScanvalidation - Example: REST API with PATCH using Field[T]
-
MarshalerTo/UnmarshalerFromstream-based interfaces - Build tag:
//go:build goexperiment.jsonv2 - Benchmark comparison: json/v1 vs json/v2
- Zero-alloc marshal (eliminate remaining allocations)
- API freeze
- awesome-go submission
- Migration guide from guregu/null
- Migration guide from
*Tpatterns - 95%+ coverage
- Security audit
opt/
├── option.go Option[T] — generic foundation
├── field.go Field[T] — three-state for PATCH
├── funcs.go Map, FlatMap, Equal, OrNull, FieldFromOption
├── string.go Concrete types (String, Int, Float, Bool, Time, ...)
├── internal/ Shared unmarshal helpers
└── zero/ Alternative semantics (zero = null)
- Generic-first —
Option[T]is the foundation, concrete types are ergonomic wrappers - No legacy — clean API from scratch, no backward compatibility burden
- Stdlib only — zero external dependencies
- Enterprise quality — benchmarks, high coverage, CI on all platforms, compile-time interface checks
- Inspired by the best — Rust
Option<T>, KotlinT?, C#Nullable<T>