Type-segregated struct decomposition for Go.
Break structs into typed maps, work with fields programmatically, reconstruct later — without knowing T.
User code knows its types. Infrastructure code doesn't need to.
// User side: knows T
type User struct {
ID string
Name string
Age int64
Balance float64
Active bool
}
atomizer, _ := atom.Use[User]()
user := &User{ID: "usr-1", Name: "Alice", Age: 30, Balance: 100.50, Active: true}
a := atomizer.Atomize(user)
// Pass atom to any library...
result := storage.Save(a) // storage never imports User
validated := validator.Check(a) // validator never imports User
transformed := migrator.Upgrade(a) // migrator never imports User
// ...get it back
restored, _ := atomizer.Deatomize(result)The receiving library sees typed maps and metadata — not T:
// Library side: doesn't know T, doesn't need T
func Save(a *atom.Atom) *atom.Atom {
// Spec describes the struct
fmt.Println(a.Spec.TypeName) // "User"
// Typed maps hold the values
for field, value := range a.Strings {
db.SetString(field, value)
}
for field, value := range a.Ints {
db.SetInt(field, value)
}
for field, value := range a.Floats {
db.SetFloat(field, value)
}
return a
}Type-safe field access. Zero knowledge of the original struct.
go get github.com/zoobz-io/atom@latestRequires Go 1.24+.
package main
import (
"fmt"
"github.com/zoobz-io/atom"
)
type Order struct {
ID string
Total float64
Status string
}
func main() {
// Register the type once
atomizer, err := atom.Use[Order]()
if err != nil {
panic(err)
}
order := &Order{ID: "order-123", Total: 99.99, Status: "pending"}
// Decompose to atom
a := atomizer.Atomize(order)
// Work with typed maps
fmt.Printf("ID: %s\n", a.Strings["ID"])
fmt.Printf("Total: %.2f\n", a.Floats["Total"])
// Modify fields
a.Strings["Status"] = "confirmed"
// Reconstruct
restored, _ := atomizer.Deatomize(a)
fmt.Printf("Status: %s\n", restored.Status) // "confirmed"
}| Feature | Description | Docs |
|---|---|---|
| Type Segregation | Strings, ints, floats, bools, times, bytes in separate typed maps | Concepts |
| Nullable Fields | Pointer types (*string, *int64) with explicit nil handling |
Basic Usage |
| Slices | []string, []int64, etc. preserved as typed slices |
Basic Usage |
| Nested Composition | Embed atoms within atoms for complex object graphs | Nested Structs |
| Field Introspection | Query fields, tables, and type metadata via Spec | API Reference |
| Custom Implementations | Atomizable/Deatomizable interfaces bypass reflection |
Interfaces |
| Code Generation | Generate implementations for zero-reflection paths | Code Generation |
- Type-safe without T — Libraries work with typed maps, not
anyor reflection - Field-level control — Read, write, transform individual fields programmatically
- Decoupled — Infrastructure code never imports user types
- Zero reflection path — Implement interfaces or use codegen for production performance
- Sentinel integration — Automatic field discovery and metadata extraction
Atom enables a pattern: user code owns types, infrastructure owns behaviour.
Your application defines structs. Libraries accept atoms. Each side works with what it knows — concrete types on one end, typed maps on the other. No shared type imports. No reflection at runtime (with codegen).
// Your domain package defines types
type User struct { ... }
type Order struct { ... }
// Storage library accepts atoms — never sees User or Order
func (s *Store) Put(a *atom.Atom) error { ... }
func (s *Store) Get(spec atom.Spec, id string) (*atom.Atom, error) { ... }
// Your code bridges the two
a := userAtomizer.Atomize(user)
store.Put(a)The contract is the Atom structure. The types stay where they belong.
- Quickstart — Get started in 5 minutes
- Core Concepts — Atoms, tables, specs
- Architecture — Internal design
- Basic Usage — Common patterns
- Custom Types — Named types and enums
- Nested Structs — Composition
- Interfaces — Custom serialization
- Testing — Test strategies
- Code Generation — Eliminating reflection
- Serialization — Encoding atoms
- Migrations — Schema evolution
- API Reference — Complete API
- Tables Reference — All table types
- Testing Reference — Test utilities
See CONTRIBUTING.md for guidelines. Run make help for available commands.
MIT License — see LICENSE for details.