da

package
v0.3.11 Latest Latest
Warning

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

Go to latest
Published: Feb 9, 2026 License: MIT Imports: 13 Imported by: 3

README

da - Dynamic Application

Easily manage massive monoliths in code

The da package provides two complementary approaches to application lifecycle management:

  • Concrete containers - define your own container struct with explicit types
  • Dynamic containers - factory pattern with reflection-based object storage

Quick Start - Concrete Containers

import "github.com/michaelquigley/df/da"

// Define your container with explicit types
type App struct {
    Config   *Config   `da:"-"`        // skip - not a component
    Database *Database `da:"order=1"`  // wire/start first
    Cache    *Cache    `da:"order=2"`  // wire/start second
    API      *Server   `da:"order=10"` // wire/start last
}

// Load config
cfg := &Config{}
da.Config(cfg, da.FileLoader("config.yaml"))

// Build container explicitly
app := &App{
    Config:   cfg,
    Database: NewDatabase(cfg.DatabaseURL),
    Cache:    NewCache(cfg.CacheURL),
    API:      NewServer(cfg.Port),
}

// Run application (wire -> start -> wait for signal -> stop)
da.Run(app)

Quick Start - Dynamic Containers

import "github.com/michaelquigley/df/da"

// Create application with config
app := da.NewApplication(config)

// Add factories to build objects
da.WithFactory(app, &DatabaseFactory{})
da.WithFactory(app, &LoggerFactory{})

// Initialize: build objects and link dependencies
app.Initialize()

// Start all startable services
app.Start()

// Clean shutdown
defer app.Stop()

Key Features

  • Concrete Containers: Type-safe, explicit dependency wiring
  • Dynamic Containers: Factory pattern with automatic object creation
  • Lifecycle Management: Wire/Initialize → Start → Stop pattern
  • Service Discovery: Find objects by type or interface
  • Configuration Loading: Flexible file-based config with loaders
  • Container Introspection: Debug and inspect container contents

Core Components

Concrete Containers
  • Wireable[C] - Interface for type-safe dependency wiring
  • Wire[C]/Start[C]/Stop[C]/Run[C] - Lifecycle functions
  • Loader - Configuration loading interface
  • Struct tags: da:"order=N" for ordering, da:"-" to skip
Dynamic Containers
  • Container - Object storage with singleton and named object support
  • Application[C] - Orchestrates object creation and lifecycle
  • Factory[C] - Interface for creating and registering objects
  • Lifecycle interfaces: Startable, Stoppable, Linkable

Object Management

Register and retrieve objects

// Store singleton objects (one per type)
da.Set(container, database)
da.SetAs[DataStore](container, database)  // store as interface

// Retrieve objects by type
db, found := da.Get[*Database](container)
stores := da.OfType[DataStore](container)  // all matching interface

// Named objects (multiple per type)
da.SetNamed(container, "primary", primaryDB)
da.SetNamed(container, "cache", cacheDB)

Factory Pattern

Create objects with dependencies

type DatabaseFactory struct{}

func (f *DatabaseFactory) Build(app *da.Application[Config]) error {
    // Get config from container
    cfg, _ := da.Get[Config](app.R)
    
    // Create and register database
    db := &Database{URL: cfg.DatabaseURL}
    da.SetAs[*Database](app.R, db)
    return nil
}

Lifecycle Management

Objects implement lifecycle interfaces

type Database struct {
    URL       string
    Connected bool
}

// da.Startable - called during app.Start()
func (d *Database) Start() error {
    return d.Connect()
}

// da.Stoppable - called during app.Stop()  
func (d *Database) Stop() error {
    d.Connected = false
    return nil
}

// da.Linkable - called after all objects created
func (d *Database) Link(container *da.Container) error {
    logger, _ := da.Get[*Logger](container)
    d.logger = logger
    return nil
}

Common Patterns

Application Bootstrap

type AppConfig struct {
    DatabaseURL string `json:"database_url"`
    LogLevel    string `json:"log_level"`
}

// Load config and create application
config := loadConfig()
app := da.NewApplication(config)

// Register all factories
da.WithFactory(app, &DatabaseFactory{})
da.WithFactory(app, &CacheFactory{})
da.WithFactory(app, &HTTPServerFactory{})

// Initialize and start
app.Initialize()  // builds all objects
app.Start()       // starts all Startable objects

Service Discovery

// Find all objects implementing an interface
allCaches := da.AsType[CacheService](container)
allStartables := da.AsType[da.Startable](container)

// Container introspection for debugging
data := container.Inspect()
fmt.Printf("Container has %d objects\n", data.Summary.Total)

Concrete Container Pattern

Define components that wire to the container

type UserService struct {
    db    *Database
    cache *Cache
}

// Wireable[App] - receives concrete container for dependency wiring
func (s *UserService) Wire(app *App) error {
    s.db = app.Database
    s.cache = app.Cache
    return nil
}

// Startable - called during da.Start()
func (s *UserService) Start() error {
    return s.db.Ping()
}

// Stoppable - called during da.Stop()
func (s *UserService) Stop() error {
    return nil
}

Configuration loading

cfg := &Config{}

// Load from required file
da.Config(cfg, da.FileLoader("config.yaml"))

// Load with optional overrides
da.Config(cfg,
    da.FileLoader("config.yaml"),
    da.OptionalFileLoader("config.local.yaml"),
)

// Chain multiple loaders
da.Config(cfg, da.ChainLoader(
    da.FileLoader("base.yaml"),
    da.OptionalFileLoader("env.yaml"),
))

Struct tags for ordering

type App struct {
    Config   *Config   `da:"-"`        // skip - not a component
    Database *Database `da:"order=1"`  // process first
    Cache    *Cache    `da:"order=2"`  // process second
    API      *Server   `da:"order=100"` // process last
}

Examples

See examples/ for tutorials:

  • da_01_hello_world - Dynamic container with factories
  • da_02_concrete_container - Concrete container pattern

Part of the df framework - dynamic foundation for Go applications

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddTagged deprecated added in v0.3.7

func AddTagged(c *Container, tag string, object any)

AddTagged adds an object to a tagged collection in the container. The same object can be added to multiple tags.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func AsType deprecated

func AsType[T any](c *Container) []T

AsType visits all objects in the container and returns any that can be cast to type T. This enables finding objects by interface or supertype regardless of their registration type.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func ClearTagged deprecated added in v0.3.7

func ClearTagged(c *Container, tag string) int

ClearTagged removes all objects with the specified tag. Returns the number of objects that were removed.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func Config added in v0.3.10

func Config[C any](cfg *C, loaders ...Loader) error

Config populates a config struct using the provided loaders. Loaders are applied in sequence; returns on first error.

func Get deprecated

func Get[T any](c *Container) (T, bool)

Get retrieves an object of type T from the container. Returns the object and true if found, or zero value and false if not found.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func GetNamed deprecated

func GetNamed[T any](c *Container, name string) (T, bool)

GetNamed retrieves a named object of type T from the container. Returns the object and true if found, or zero value and false if not found.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func Has deprecated

func Has[T any](c *Container) bool

Has checks if an object of type T exists in the container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func HasNamed deprecated

func HasNamed[T any](c *Container, name string) bool

HasNamed checks if a named object of type T with the given name exists in the container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func HasTagged deprecated added in v0.3.7

func HasTagged(c *Container, tag string) bool

HasTagged checks if any objects exist with the specified tag.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func OfType deprecated

func OfType[T any](c *Container) []T

OfType retrieves all objects of type T from the container (singleton, named, and tagged). Returns a slice containing the singleton (if exists), followed by named instances, then tagged instances. Duplicate objects (same pointer instance in multiple locations) are deduplicated.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func Remove deprecated

func Remove[T any](c *Container) bool

Remove removes an object of type T from the container. Returns true if the object was found and removed, false if it didn't exist.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func RemoveNamed deprecated

func RemoveNamed[T any](c *Container, name string) bool

RemoveNamed removes a named object of type T with the given name from the container. Returns true if the object was found and removed, false if it didn't exist.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func RemoveTagged deprecated added in v0.3.7

func RemoveTagged(c *Container, object any) int

RemoveTagged removes a specific object from ALL tags. Returns the number of tags the object was removed from.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func RemoveTaggedFrom deprecated added in v0.3.7

func RemoveTaggedFrom(c *Container, tag string, object any) bool

RemoveTaggedFrom removes a specific object from a specific tag. Returns true if the object was found and removed, false otherwise.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func Run added in v0.3.10

func Run[C any](c *C) error

Run is a convenience function that: Wire -> Start -> wait for signal -> Stop. Blocks until SIGINT or SIGTERM is received.

func Set deprecated

func Set(c *Container, object any)

Set registers a singleton object in the container by its type. If an object of the same type already exists, it will be replaced.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func SetAs deprecated

func SetAs[T any](c *Container, object T)

SetAs registers a singleton object in the container by the specified type. If an object of the same type already exists, it will be replaced.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func SetNamed deprecated

func SetNamed(c *Container, name string, object any)

SetNamed registers a named object in the container by its type and name. If an object with the same type and name already exists, it will be replaced.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func Start added in v0.3.10

func Start[C any](c *C) error

Start calls Start() on all Startable components in the container. Components are processed in order specified by `da:"order=N"` tags.

func Stop added in v0.3.10

func Stop[C any](c *C) error

Stop calls Stop() on all Stoppable components in the container. Components are processed in reverse order of `da:"order=N"` tags. Continues on error and returns the first error encountered.

func Tagged deprecated added in v0.3.7

func Tagged(c *Container, tag string) []any

Tagged retrieves all objects with the specified tag.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func TaggedAsType deprecated added in v0.3.7

func TaggedAsType[T any](c *Container, tag string) []T

TaggedAsType retrieves all objects with the specified tag that can be cast to type T. This enables finding tagged objects by interface regardless of their concrete type.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func TaggedOfType deprecated added in v0.3.7

func TaggedOfType[T any](c *Container, tag string) []T

TaggedOfType retrieves all objects with the specified tag that are of type T.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func WaitForSignal added in v0.3.10

func WaitForSignal()

WaitForSignal blocks until SIGINT or SIGTERM is received.

func Wire added in v0.3.10

func Wire[C any](c *C) error

Wire calls Wire(c) on all Wireable[C] components in the container. Components are processed in order specified by `da:"order=N"` tags.

Types

type Application deprecated

type Application[C any] struct {
	Cfg       C            // configuration object
	C         *Container   // container
	Factories []Factory[C] // factories for creating and registering objects
}

Application orchestrates the lifecycle of a container with configuration. It manages object creation through factories, linking, startup, and shutdown phases.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func NewApplication deprecated

func NewApplication[C any](cfg C) *Application[C]

NewApplication creates a new application with the given configuration. The configuration object is automatically registered in the container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func WithFactory deprecated

func WithFactory[C any](a *Application[C], f Factory[C]) *Application[C]

WithFactory adds a factory to the application for fluent configuration. Returns the application to enable method chaining.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func WithFactoryFunc deprecated

func WithFactoryFunc[C any](a *Application[C], f func(a *Application[C]) error) *Application[C]

WithFactoryFunc adds a function factory to the application for fluent configuration. Returns the application to enable method chaining.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) Build deprecated

func (a *Application[C]) Build() error

Build executes all registered factories to create and register objects in the container. Factories are responsible for calling SetAs[T]() to register their created objects.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) Configure deprecated

func (a *Application[C]) Configure(path string, opts ...*dd.Options) error

Configure loads additional configuration from a file and merges it with the existing configuration. Supports JSON and YAML file formats based on file extension.

Deprecated: Use da.Config with FileLoader instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) Initialize deprecated

func (a *Application[C]) Initialize(configPaths ...string) error

Initialize executes Configure, Build, and Link phases in sequence. Returns on first error without proceeding to subsequent phases.

Deprecated: Use concrete container pattern with da.Wire instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) InitializeWithOptions deprecated

func (a *Application[C]) InitializeWithOptions(opts *dd.Options, configPaths ...string) error

InitializeWithOptions executes Configure, Build, and Link phases in sequence with custom options. Returns on first error without proceeding to subsequent phases.

Deprecated: Use concrete container pattern with da.Wire instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) InitializeWithPaths deprecated added in v0.3.5

func (a *Application[C]) InitializeWithPaths(configPaths ...ConfigPath) error

InitializeWithPaths executes Configure, Build, and Link phases in sequence. Config paths can be marked as optional using OptionalPath(), which will skip missing files without returning an error. Required paths (using RequiredPath()) will fail if missing.

Deprecated: Use concrete container pattern with da.Wire instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) InitializeWithPathsAndOptions deprecated added in v0.3.5

func (a *Application[C]) InitializeWithPathsAndOptions(opts *dd.Options, configPaths ...ConfigPath) error

InitializeWithPathsAndOptions executes Configure, Build, and Link phases in sequence with custom options. Config paths can be marked as optional using OptionalPath(), which will skip missing files without returning an error. Required paths (using RequiredPath()) will fail if missing. Non-existence errors are only ignored for optional paths; other errors (permissions, malformed files, etc.) are always returned regardless of the optional flag.

Deprecated: Use concrete container pattern with da.Wire instead. See da/examples/da_02_concrete_container for migration guidance.

func (a *Application[C]) Link() error

Link establishes dependencies between objects by calling Link() on all Linkable objects. This phase occurs after Build() to ensure all objects exist before dependency resolution. Returns the first error encountered, which stops the linking process.

Deprecated: Use da.Wire with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) Start deprecated

func (a *Application[C]) Start() error

Start initializes all Startable objects after linking is complete. Returns the first error encountered, which stops the startup process.

Deprecated: Use da.Start with concrete container instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Application[C]) Stop deprecated

func (a *Application[C]) Stop() error

Stop shuts down all Stoppable objects for graceful cleanup. Returns the first error encountered, but continues attempting to stop remaining objects.

Deprecated: Use da.Stop with concrete container instead. See da/examples/da_02_concrete_container for migration guidance.

type ConfigPath deprecated added in v0.3.5

type ConfigPath struct {
	Path     string
	Optional bool
}

ConfigPath represents a configuration file path with optional loading behavior. When Optional is true, the file will be skipped if it doesn't exist without returning an error.

Deprecated: Use da.Config with FileLoader/OptionalFileLoader instead. See da/examples/da_02_concrete_container for migration guidance.

func OptionalPath deprecated added in v0.3.5

func OptionalPath(path string) ConfigPath

OptionalPath creates a ConfigPath for an optional configuration file. If the file doesn't exist, it will be silently skipped during initialization.

Deprecated: Use da.Config with OptionalFileLoader instead. See da/examples/da_02_concrete_container for migration guidance.

func RequiredPath deprecated added in v0.3.5

func RequiredPath(path string) ConfigPath

RequiredPath creates a ConfigPath for a required configuration file. If the file doesn't exist, initialization will fail with an error.

Deprecated: Use da.Config with FileLoader instead. See da/examples/da_02_concrete_container for migration guidance.

type Container deprecated

type Container struct {
	// contains filtered or unexported fields
}

Container is an application container that manages singletons and objects by type and (optionally) by name.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func NewContainer deprecated

func NewContainer() *Container

NewContainer creates and returns a new empty container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Container) Clear deprecated

func (c *Container) Clear()

Clear removes all objects from the container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Container) Inspect deprecated

func (c *Container) Inspect(format InspectFormat) (string, error)

Inspect returns a formatted representation of the container contents. Supports table, JSON, and YAML formats for human and machine consumption.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Container) Tags deprecated added in v0.3.7

func (c *Container) Tags() []string

Tags returns a slice of all tags in the container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Container) Types deprecated

func (c *Container) Types() []reflect.Type

Types returns a slice of all registered types in the container. Useful for debugging and introspection.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (*Container) Visit deprecated

func (c *Container) Visit(f func(object any) error) error

Visit calls the provided function for each object in the container. Objects that appear in multiple locations (e.g., both as singleton and tagged) are only visited once.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

type Factory deprecated

type Factory[C any] interface {
	Build(a *Application[C]) error
}

Factory creates and registers objects in the application container. Implementations should use SetAs[T]() to register created objects with the container.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

type FactoryFunc deprecated

type FactoryFunc[C any] func(a *Application[C]) error

FactoryFunc is a function type that implements Factory[C]. It allows using raw functions as factories without defining separate types.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

func (FactoryFunc[C]) Build deprecated

func (f FactoryFunc[C]) Build(a *Application[C]) error

Build implements the Factory interface for FactoryFunc.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

type InspectData

type InspectData struct {
	Summary InspectSummary  `json:"summary" yaml:"summary"`
	Objects []InspectObject `json:"objects" yaml:"objects"`
}

InspectData represents the structured data for container inspection.

type InspectFormat deprecated

type InspectFormat string

InspectFormat defines the output format for container inspection.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

const (
	InspectHuman InspectFormat = "human"
	InspectJSON  InspectFormat = "json"
	InspectYAML  InspectFormat = "yaml"
)

type InspectObject

type InspectObject struct {
	Type    string  `json:"type" yaml:"type"`
	Storage string  `json:"storage" yaml:"storage"`
	Name    *string `json:"name,omitempty" yaml:"name,omitempty"`
	Tag     *string `json:"tag,omitempty" yaml:"tag,omitempty"`
	Value   string  `json:"value" yaml:"value"`
}

InspectObject represents a single object in the container for inspection.

type InspectSummary

type InspectSummary struct {
	Total      int `json:"total" yaml:"total"`
	Singletons int `json:"singletons" yaml:"singletons"`
	Named      int `json:"named" yaml:"named"`
	Tagged     int `json:"tagged" yaml:"tagged"`
}

InspectSummary provides aggregate statistics about the container.

type Linkable deprecated

type Linkable interface {
	Link(*Container) error
}

Linkable defines objects that can establish connections to other container objects during the linking phase after all objects have been created.

Deprecated: Use concrete container pattern with Wireable[C] instead. See da/examples/da_02_concrete_container for migration guidance.

type Loader added in v0.3.10

type Loader interface {
	Load(dest any) error
}

Loader defines how configuration is loaded from a source.

func ChainLoader added in v0.3.10

func ChainLoader(loaders ...Loader) Loader

ChainLoader creates a loader that applies multiple loaders in sequence. Returns on first error.

func FileLoader added in v0.3.10

func FileLoader(paths ...string) Loader

FileLoader creates a loader for required config files. File format is determined by extension (.json, .yaml, .yml). Returns error if any file doesn't exist or can't be parsed.

func OptionalFileLoader added in v0.3.10

func OptionalFileLoader(paths ...string) Loader

OptionalFileLoader creates a loader that skips missing files. File format is determined by extension (.json, .yaml, .yml). Missing files are silently skipped; other errors are returned.

type Startable

type Startable interface {
	Start() error
}

Startable defines objects that require initialization after linking is complete.

type Stoppable

type Stoppable interface {
	Stop() error
}

Stoppable defines objects that require cleanup during shutdown.

type Wireable added in v0.3.10

type Wireable[C any] interface {
	Wire(c *C) error
}

Wireable receives the concrete container for wiring dependencies. Components implement this interface with their specific container type to receive the container during the wiring phase.

This is used with the concrete container pattern where developers define their own container struct with explicit types, as opposed to the reflection-based Container type.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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