di

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 2, 2026 License: MIT Imports: 6 Imported by: 0

README

di

Dependency injection container with eager/lazy registration, singletons, circuit breakers, and generics.

Install

go get github.com/kbukum/gokit

Quick Start

package main

import (
    "fmt"
    "github.com/kbukum/gokit/di"
)

func main() {
    c := di.NewContainer()

    // Register a singleton
    c.RegisterSingleton("greeting", "Hello, World!")

    // Register a lazy constructor
    c.RegisterLazy("service", func() (string, error) {
        return "initialized on first resolve", nil
    })

    // Type-safe resolve
    val, err := di.Resolve[string](c, "greeting")
    if err != nil {
        panic(err)
    }
    fmt.Println(val) // "Hello, World!"

    // Must resolve (panics on error)
    svc := di.MustResolve[string](c, "service")
    fmt.Println(svc)

    c.Close()
}

Key Types & Functions

Name Description
Container DI container interface
NewContainer() / NewSimpleContainer() Container constructors
Register() / RegisterLazy() / RegisterEager() Registration modes
RegisterSingleton() Register a pre-built instance
Resolve[T]() / MustResolve[T]() / TryResolve[T]() Type-safe generic resolution
WithRetryPolicy() / WithCircuitBreaker() Lazy registration options
CircuitBreaker / CircuitBreakerConfig Built-in circuit breaker for lazy deps

⬅ Back to main README

Documentation

Overview

Package di provides a dependency injection container for gokit applications.

It supports eager, lazy, and singleton registration modes with type-safe resolution using Go generics. The container enables decoupled architecture by managing service dependencies and their lifecycle.

Registration

di.Register[MyService](container, func() (*MyService, error) {
    return NewMyService(), nil
})

Resolution

svc := di.MustResolve[MyService](container)

Index

Constants

This section is empty.

Variables

View Source
var Pkg = PkgNames{

	Config:           "config",
	Logger:           "logger",
	Database:         "database",
	Redis:            "redis",
	Storage:          "storage",
	Workload:         "workload",
	ServiceRegistry:  "service_registry",
	ServiceDiscovery: "service_discovery",

	HTTPServer:    "http_server",
	GRPCServer:    "grpc_server",
	UnifiedServer: "unified_server",

	KafkaProducer:      "kafka_producer",
	KafkaConsumer:      "kafka_consumer",
	KafkaConsumerGroup: "kafka_consumer_group",

	SSEHub: "sse_hub",
}

Pkg contains all component names for the pkg bootstrap layer.

Functions

func GetTypedResolver

func GetTypedResolver[T any](container Container, name string) func() (T, error)

GetTypedResolver returns a type-safe resolver function.

func MustResolve

func MustResolve[T any](c Container, key string) T

MustResolve resolves a component with type safety, panics on error. Use this in handlers when you need a dependency.

Example:

botRepo := di.MustResolve[contracts.BotRepository](h.container, shareddi.Shared.BotRepository)

func Resolve

func Resolve[T any](c Container, key string) (T, error)

Resolve resolves a component with type safety, returns error on failure. Use this when you want to handle resolution errors gracefully.

Example:

botRepo, err := di.Resolve[contracts.BotRepository](c, shareddi.Shared.BotRepository)
if err != nil {
    return fmt.Errorf("failed to get bot repository: %w", err)
}

func ResolveTyped

func ResolveTyped[T any](container Container, name string) (T, error)

ResolveTyped provides type-safe resolution with generics.

func TryResolve

func TryResolve[T any](c Container, key string) (T, bool)

TryResolve resolves a component, returns zero value and false if not found. Use this when a dependency is optional.

Example:

if metrics, ok := di.TryResolve[MetricsClient](c, "metrics"); ok {
    metrics.RecordEvent(...)
}

Types

type CircuitBreaker

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

func NewCircuitBreaker

func NewCircuitBreaker(config *CircuitBreakerConfig) *CircuitBreaker

func (*CircuitBreaker) IsOpen

func (cb *CircuitBreaker) IsOpen() bool

func (*CircuitBreaker) RecordFailure

func (cb *CircuitBreaker) RecordFailure()

func (*CircuitBreaker) RecordSuccess

func (cb *CircuitBreaker) RecordSuccess()

type CircuitBreakerConfig

type CircuitBreakerConfig struct {
	FailureThreshold  int
	RecoveryTimeoutMs int
	HalfOpenRequests  int
}

type CircuitState

type CircuitState int
const (
	CircuitClosed CircuitState = iota
	CircuitOpen
	CircuitHalfOpen
)

type ComponentRegistration

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

type Container

type Container interface {
	Register(key string, constructor interface{}) error
	RegisterLazy(key string, constructor interface{}, options ...LazyOption) error
	RegisterEager(key string, constructor interface{}) error
	Resolve(key string) (interface{}, error)
	RegisterSingleton(key string, instance interface{}) error
	Close() error

	// Introspection
	Registrations() []RegistrationInfo

	// Legacy methods for backward compatibility
	InvalidateCache(name string) error
	Refresh(name string) (interface{}, error)
	GetResolver(name string) func() (interface{}, error)
	MustResolve(name string) interface{}
}

Container defines the interface for a dependency injection container

func NewContainer

func NewContainer() Container

func NewSimpleContainer

func NewSimpleContainer() Container

NewSimpleContainer creates the new unified container (backward compatibility)

type LazyOption

type LazyOption func(*ComponentRegistration)

func WithCircuitBreaker

func WithCircuitBreaker(config *CircuitBreakerConfig) LazyOption

func WithRetryPolicy

func WithRetryPolicy(policy *RetryPolicy) LazyOption

Helper functions and options

type PkgNames

type PkgNames struct {
	// Core infrastructure
	Config           string
	Logger           string
	Database         string
	Redis            string
	Storage          string
	Workload         string
	ServiceRegistry  string
	ServiceDiscovery string

	// HTTP/gRPC servers
	HTTPServer    string
	GRPCServer    string
	UnifiedServer string

	// Messaging
	KafkaProducer      string
	KafkaConsumer      string
	KafkaConsumerGroup string

	// Real-time
	SSEHub string
}

PkgNames defines the base layer component names for the pkg bootstrap layer. Projects embed this struct in their own shared/service DI names.

type RegistrationInfo

type RegistrationInfo struct {
	Key         string
	Mode        RegistrationMode // Eager, Lazy, or Singleton
	Initialized bool
}

RegistrationInfo describes a registered component for introspection.

type RegistrationMode

type RegistrationMode int

RegistrationMode determines how a component should be resolved

const (
	Eager     RegistrationMode = iota // Initialize immediately on registration
	Lazy                              // Initialize on first resolve
	Singleton                         // Pre-created instance
)

type RetryPolicy

type RetryPolicy struct {
	MaxAttempts       int
	InitialBackoffMs  int
	MaxBackoffMs      int
	BackoffMultiplier float64
}

type UnifiedContainer

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

UnifiedContainer is our single, unified DI container

func (*UnifiedContainer) Close

func (c *UnifiedContainer) Close() error

func (*UnifiedContainer) GetResolver

func (c *UnifiedContainer) GetResolver(name string) func() (interface{}, error)

func (*UnifiedContainer) InvalidateCache

func (c *UnifiedContainer) InvalidateCache(name string) error

Legacy methods for backward compatibility

func (*UnifiedContainer) MustResolve

func (c *UnifiedContainer) MustResolve(name string) interface{}

func (*UnifiedContainer) Refresh

func (c *UnifiedContainer) Refresh(name string) (interface{}, error)

func (*UnifiedContainer) Register

func (c *UnifiedContainer) Register(key string, constructor interface{}) error

Register component with lazy loading by default (most common case)

func (*UnifiedContainer) RegisterEager

func (c *UnifiedContainer) RegisterEager(key string, constructor interface{}) error

RegisterEager registers a component for immediate initialization

func (*UnifiedContainer) RegisterLazy

func (c *UnifiedContainer) RegisterLazy(key string, constructor interface{}, options ...LazyOption) error

RegisterLazy registers a component for lazy initialization

func (*UnifiedContainer) RegisterSingleton

func (c *UnifiedContainer) RegisterSingleton(key string, instance interface{}) error

RegisterSingleton registers a pre-created instance

func (*UnifiedContainer) Registrations

func (c *UnifiedContainer) Registrations() []RegistrationInfo

Registrations returns info about all registered components for introspection.

func (*UnifiedContainer) Resolve

func (c *UnifiedContainer) Resolve(key string) (interface{}, error)

Resolve gets a component instance

Jump to

Keyboard shortcuts

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