Documentation
¶
Index ¶
- Constants
- Variables
- func As[Initial any, Alias any](i Injector) error
- func AsNamed[Initial any, Alias any](i Injector, initial string, alias string) error
- func Bind[Initial any, Alias any]() func(Injector)
- func BindNamed[Initial any, Alias any](initial string, alias string) func(Injector)
- func Eager[T any](value T) func(Injector)
- func EagerNamed[T any](serviceName string, value T) func(Injector)
- func HealthCheck[T any](i Injector) error
- func HealthCheckNamed(i Injector, name string) error
- func HealthCheckNamedWithContext(ctx context.Context, i Injector, name string) error
- func HealthCheckWithContext[T any](ctx context.Context, i Injector) error
- func Invoke[T any](i Injector) (T, error)
- func InvokeAs[T any](i Injector) (T, error)
- func InvokeNamed[T any](i Injector, name string) (T, error)
- func InvokeStruct[T any](i Injector) (T, error)
- func Lazy[T any](p Provider[T]) func(Injector)
- func LazyNamed[T any](serviceName string, p Provider[T]) func(Injector)
- func MustAs[Initial any, Alias any](i Injector)
- func MustAsNamed[Initial any, Alias any](i Injector, initial string, alias string)
- func MustInvoke[T any](i Injector) T
- func MustInvokeAs[T any](i Injector) T
- func MustInvokeNamed[T any](i Injector, name string) T
- func MustInvokeStruct[T any](i Injector) T
- func MustShutdown[T any](i Injector)
- func MustShutdownNamed(i Injector, name string)
- func MustShutdownNamedWithContext(ctx context.Context, i Injector, name string)
- func MustShutdownWithContext[T any](ctx context.Context, i Injector)
- func NameOf[T any]() string
- func Override[T any](i Injector, provider Provider[T])
- func OverrideNamed[T any](i Injector, name string, provider Provider[T])
- func OverrideNamedTransient[T any](i Injector, name string, provider Provider[T])
- func OverrideNamedValue[T any](i Injector, name string, value T)
- func OverrideTransient[T any](i Injector, provider Provider[T])
- func OverrideValue[T any](i Injector, value T)
- func Package(services ...func(i Injector)) func(Injector)
- func Provide[T any](i Injector, provider Provider[T])
- func ProvideNamed[T any](i Injector, name string, provider Provider[T])
- func ProvideNamedTransient[T any](i Injector, name string, provider Provider[T])
- func ProvideNamedValue[T any](i Injector, name string, value T)
- func ProvideTransient[T any](i Injector, provider Provider[T])
- func ProvideValue[T any](i Injector, value T)
- func Shutdown[T any](i Injector) error
- func ShutdownNamed(i Injector, name string) error
- func ShutdownNamedWithContext(ctx context.Context, i Injector, name string) error
- func ShutdownWithContext[T any](ctx context.Context, i Injector) error
- func Transient[T any](p Provider[T]) func(Injector)
- func TransientNamed[T any](serviceName string, p Provider[T]) func(Injector)
- type DAG
- type ExplainInjectorOutput
- type ExplainInjectorScopeOutput
- type ExplainInjectorServiceOutput
- type ExplainServiceDependencyOutput
- type ExplainServiceOutput
- type Healthchecker
- type HealthcheckerWithContext
- type Injector
- type InjectorOpts
- type Provider
- type RootScope
- func (s *RootScope) AddAfterInvocationHook(hook func(*Scope, string, error))
- func (s *RootScope) AddAfterRegistrationHook(hook func(*Scope, string))
- func (s *RootScope) AddAfterShutdownHook(hook func(*Scope, string, error))
- func (s *RootScope) AddBeforeInvocationHook(hook func(*Scope, string))
- func (s *RootScope) AddBeforeRegistrationHook(hook func(*Scope, string))
- func (s *RootScope) AddBeforeShutdownHook(hook func(*Scope, string))
- func (s *RootScope) Ancestors() []*Scope
- func (s *RootScope) ChildByID(id string) (*Scope, bool)
- func (s *RootScope) ChildByName(name string) (*Scope, bool)
- func (s *RootScope) Children() []*Scope
- func (s *RootScope) Clone() *RootScope
- func (s *RootScope) CloneWithOpts(opts *InjectorOpts) *RootScope
- func (s *RootScope) HealthCheck() map[string]error
- func (s *RootScope) HealthCheckWithContext(ctx context.Context) map[string]error
- func (s *RootScope) ID() string
- func (s *RootScope) ListInvokedServices() []ServiceDescription
- func (s *RootScope) ListProvidedServices() []ServiceDescription
- func (s *RootScope) Name() string
- func (s *RootScope) RootScope() *RootScope
- func (s *RootScope) Scope(name string, p ...func(Injector)) *Scope
- func (s *RootScope) Shutdown() *ShutdownReport
- func (s *RootScope) ShutdownOnSignals(signals ...os.Signal) (os.Signal, *ShutdownReport)
- func (s *RootScope) ShutdownOnSignalsWithContext(ctx context.Context, signals ...os.Signal) (os.Signal, *ShutdownReport)
- func (s *RootScope) ShutdownWithContext(ctx context.Context) *ShutdownReport
- type Scope
- func (s *Scope) Ancestors() []*Scope
- func (s *Scope) ChildByID(id string) (*Scope, bool)
- func (s *Scope) ChildByName(name string) (*Scope, bool)
- func (s *Scope) Children() []*Scope
- func (s *Scope) HealthCheck() map[string]error
- func (s *Scope) HealthCheckWithContext(ctx context.Context) map[string]error
- func (s *Scope) ID() string
- func (s *Scope) ListInvokedServices() []ServiceDescription
- func (s *Scope) ListProvidedServices() []ServiceDescription
- func (s *Scope) Name() string
- func (s *Scope) RootScope() *RootScope
- func (s *Scope) Scope(name string, packages ...func(Injector)) *Scope
- func (s *Scope) Shutdown() *ShutdownReport
- func (s *Scope) ShutdownWithContext(ctx context.Context) *ShutdownReport
- type ServiceDescription
- type ServiceType
- type ShutdownReport
- type Shutdowner
- type ShutdownerWithContext
- type ShutdownerWithContextAndError
- type ShutdownerWithError
Constants ¶
const DefaultRootScopeName = "[root]"
DefaultRootScopeName is the default name for the root scope.
const DefaultStructTagKey = "do"
DefaultStructTagKey is the default tag key used for struct field injection. When using struct injection, fields can be tagged with `do:""` or `do:"service-name"` to specify which service should be injected.
Variables ¶
var ( //nolint:revive ErrServiceNotFound = errors.New("DI: could not find service") ErrServiceNotMatch = errors.New("DI: could not find service satisfying interface") ErrCircularDependency = errors.New("DI: circular dependency detected") ErrHealthCheckTimeout = errors.New("DI: health check timeout") )
var DefaultRootScope = New()
DefaultRootScope is a global instance of the root scope that can be used for simple dependency injection scenarios without creating a custom scope.
var MaxInvocationFrames uint32 = 100
MaxInvocationFrames defines the maximum number of stack frames to capture when tracking service invocations for debugging and observability purposes.
Functions ¶
func As ¶
As declares an alias for a service, allowing it to be retrieved using a different type. This function creates a type alias where the Alias type can be used to retrieve the Initial service. The alias is automatically named using the type name of Alias.
Parameters:
- i: The injector to register the alias in
Returns an error if the alias cannot be created (e.g., type incompatibility or missing service).
Example:
// Register a concrete service
do.Provide(injector, func(i do.Injector) (*PostgresqlDatabase, error) {
return &PostgresqlDatabase{}, nil
})
// Create an alias so it can be retrieved as an interface
do.As[*PostgresqlDatabase, Database](injector)
// Now both work:
db := do.MustInvoke[*PostgresqlDatabase](injector)
db := do.MustInvoke[Database](injector)
func AsNamed ¶
AsNamed declares a named alias for a named service. This function allows you to create aliases with custom names for both the initial service and the alias.
Parameters:
- i: The injector to register the alias in
- initial: The name of the existing service to alias
- alias: The name for the new alias service
Returns an error if the alias cannot be created (e.g., type incompatibility or missing service).
Example:
// Register a service with a custom name
do.ProvideNamed(injector, "my-db", func(i do.Injector) (*PostgresqlDatabase, error) {
return &PostgresqlDatabase{}, nil
})
// Create an alias with custom names
do.AsNamed[*PostgresqlDatabase, Database](injector, "my-db", "db-interface")
// Retrieve using the alias name
db := do.MustInvokeNamed[Database](injector, "db-interface")
func Bind ¶
Bind creates a function that creates a type alias between two types. This function is a convenience wrapper for creating service binding functions that can be used in packages.
Parameters:
- Initial: The original type to bind from
- Alias: The type to bind to (must be implemented by Initial)
Returns a function that creates the type alias when executed. Panics if the binding cannot be created.
Example:
dbBinding := do.Bind[*Database, DatabaseInterface]() // Global to a package var Package = do.Package(dbBinding, ...)
func BindNamed ¶
BindNamed creates a function that creates a named type alias between two types. This function is a convenience wrapper for creating named service binding functions that can be used in packages.
Parameters:
- initial: The name of the original service
- alias: The name for the alias service
- Initial: The original type to bind from
- Alias: The type to bind to (must be implemented by Initial)
Returns a function that creates the named type alias when executed. Panics if the binding cannot be created.
Example:
dbBinding := do.BindNamed[*Database, DatabaseInterface]("main-db", "db-interface")
// Global to a package
var Package = do.Package(dbBinding, ...)
func Eager ¶
Eager creates a function that registers an eager service using the default service name. This function is a convenience wrapper for creating eager service registration functions that can be used in packages. The service value is provided directly.
Parameters:
- value: The service instance to register eagerly
Returns a function that registers the service as eager when executed.
Example:
configService := do.Eager[*Config](&Config{Port: 8080})
// Global to a package
var Package = do.Package(configService)
func EagerNamed ¶
EagerNamed creates a function that registers an eager service with a custom name. This function is a convenience wrapper for creating named eager service registration functions that can be used in packages. The service value is provided directly.
Parameters:
- serviceName: The custom name for the service
- value: The service instance to register eagerly
Returns a function that registers the service as eager with the specified name when executed.
Example:
configService := do.EagerNamed[*Config]("app-config", &Config{Port: 8080})
// Global to a package
var Package = do.Package(configService, ...)
func HealthCheck ¶
HealthCheck returns a service status, using type inference to determine the service name. This function performs a health check on a service by inferring its name from the type T. The service must implement either Healthchecker or HealthcheckerWithContext interface.
Parameters:
- i: The injector containing the service
Returns an error if the health check fails, or nil if the service is healthy.
Example:
err := do.HealthCheck[*Database](injector)
if err != nil {
log.Printf("Database health check failed: %v", err)
}
func HealthCheckNamed ¶
HealthCheckNamed returns a service status for a named service. This function performs a health check on a service with the specified name. The service must implement either Healthchecker or HealthcheckerWithContext interface.
Parameters:
- i: The injector containing the service
- name: The name of the service to health check
Returns an error if the health check fails, or nil if the service is healthy.
Example:
err := do.HealthCheckNamed(injector, "main-database")
if err != nil {
log.Printf("Main database health check failed: %v", err)
}
func HealthCheckNamedWithContext ¶
HealthCheckNamedWithContext returns a service status for a named service with context support. This function performs a health check on a service with the specified name and context support for timeout and cancellation. The service must implement either Healthchecker or HealthcheckerWithContext interface.
Parameters:
- ctx: Context for cancellation and timeout control
- i: The injector containing the service
- name: The name of the service to health check
Returns an error if the health check fails, or nil if the service is healthy.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := do.HealthCheckNamedWithContext(ctx, injector, "main-database")
if err != nil {
log.Printf("Main database health check failed: %v", err)
}
func HealthCheckWithContext ¶
HealthCheckWithContext returns a service status, using type inference to determine the service name. This function performs a health check on a service with context support for timeout and cancellation. The service must implement either Healthchecker or HealthcheckerWithContext interface.
Parameters:
- ctx: Context for cancellation and timeout control
- i: The injector containing the service
Returns an error if the health check fails, or nil if the service is healthy.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := do.HealthCheckWithContext[*Database](ctx, injector)
if err != nil {
log.Printf("Database health check failed: %v", err)
}
func Invoke ¶
Invoke retrieves and instantiates a service from the DI container using type inference. The service will be created if it hasn't been instantiated yet (for lazy services).
Example:
service, err := do.Invoke[*MyService](injector)
func InvokeAs ¶
InvokeAs invokes a service in the DI container by finding the first service that matches the provided type or interface. This function searches through all registered services to find one that can be cast to the requested type T. It's useful when you want to retrieve a service by interface without explicitly creating aliases.
Parameters:
- i: The injector to search for the service
Returns the service instance and any error that occurred during invocation.
Example:
// Register a concrete service
do.Provide(injector, func(i do.Injector) (*PostgresqlDatabase, error) {
return &PostgresqlDatabase{}, nil
})
// Retrieve by interface
db, err := do.InvokeAs[Database](injector)
func InvokeNamed ¶
InvokeNamed retrieves and instantiates a named service from the DI container. This allows you to retrieve specific named services when multiple services of the same type are registered.
Example:
// Register multiple databases
do.ProvideNamed(injector, "main-db", func(i do.Injector) (*Database, error) {
return &Database{URL: "postgres://main.acme.dev:5432/db"}, nil
})
do.ProvideNamed(injector, "backup-db", func(i do.Injector) (*Database, error) {
return &Database{URL: "postgres://backup.acme.dev:5432/db"}, nil
})
// Retrieve specific database
mainDB, err := do.InvokeNamed[*Database](injector, "main-db")
backupDB, err := do.InvokeNamed[*Database](injector, "backup-db")
func InvokeStruct ¶
InvokeStruct invokes services located in struct properties. The struct fields must be tagged with `do:""` or `do:"name"`, where `name` is the service name in the DI container. If the service is not found in the DI container, an error is returned. If the service is found but not assignable to the struct field, an error is returned.
Example:
type App struct {
Database *Database `do:""`
Logger *Logger `do:"app-logger"`
Config *Config `do:""`
}
// Register services
do.Provide(injector, func(i do.Injector) (*Database, error) {
return &Database{}, nil
})
do.ProvideNamed(injector, "app-logger", func(i do.Injector) (*Logger, error) {
return &Logger{}, nil
})
do.Provide(injector, func(i do.Injector) (*Config, error) {
return &Config{}, nil
})
// Invoke struct with injected services
app, err := do.InvokeStruct[App](injector)
func Lazy ¶
Lazy creates a function that registers a lazy service using the default service name. This function is a convenience wrapper for creating lazy service registration functions that can be used in packages.
Parameters:
- p: The provider function that creates the service instance
Returns a function that registers the service as lazy when executed.
Example:
dbService := do.Lazy[*Database](func(i do.Injector) (*Database, error) {
return &Database{}, nil
})
// Global to a package
var Package = do.Package(dbService, ...)
func LazyNamed ¶
LazyNamed creates a function that registers a lazy service with a custom name. This function is a convenience wrapper for creating named lazy service registration functions that can be used in packages.
Parameters:
- serviceName: The custom name for the service
- p: The provider function that creates the service instance
Returns a function that registers the service as lazy with the specified name when executed.
Example:
dbService := do.LazyNamed[*Database]("main-db", func(i do.Injector) (*Database, error) {
return &Database{}, nil
})
// Global to a package
var Package = do.Package(dbService)
func MustAs ¶
MustAs declares an alias for a service and panics if an error occurs. This is a convenience function that wraps As and panics on error.
Parameters:
- i: The injector to register the alias in
Panics if the alias cannot be created (e.g., type incompatibility or missing service).
Example:
do.MustAs[*PostgresqlDatabase, Database](injector)
func MustAsNamed ¶
MustAsNamed declares a named alias for a named service and panics if an error occurs. This is a convenience function that wraps AsNamed and panics on error.
Parameters:
- i: The injector to register the alias in
- initial: The name of the existing service to alias
- alias: The name for the new alias service
Panics if the alias cannot be created (e.g., type incompatibility or missing service).
Example:
do.MustAsNamed[*PostgresqlDatabase, Database](injector, "my-db", "db-interface")
func MustInvoke ¶
MustInvoke retrieves and instantiates a service from the DI container using type inference. If the service cannot be retrieved or instantiated, it panics.
This function is useful when you're certain the service exists and want to avoid error handling in your code.
Example:
service := do.MustInvoke[*MyService](injector)
func MustInvokeAs ¶
MustInvokeAs invokes a service in the DI container by finding the first service that matches the provided type or interface. This function panics if an error occurs during invocation. It's useful when you want to retrieve a service by interface without explicitly creating aliases.
Parameters:
- i: The injector to search for the service
Returns the service instance. Panics if the service cannot be found or invoked.
Example:
// Register a concrete service
do.Provide(injector, func(i do.Injector) (*PostgresqlDatabase, error) {
return &PostgresqlDatabase{}, nil
})
// Retrieve by interface
db := do.MustInvokeAs[Database](injector)
func MustInvokeNamed ¶
MustInvokeNamed retrieves and instantiates a named service from the DI container. If the service cannot be retrieved or instantiated, it panics.
This function is useful when you're certain the named service exists and want to avoid error handling in your code.
Example:
service := do.MustInvokeNamed[*MyService](injector, "my-service")
func MustInvokeStruct ¶
MustInvokeStruct invokes services located in struct properties and panics on error. The struct fields must be tagged with `do:""` or `do:"name"`, where `name` is the service name in the DI container. If the service is not found in the DI container, it panics. If the service is found but not assignable to the struct field, it panics.
Example:
type App struct {
Database *Database `do:""`
Logger *Logger `do:"app-logger"`
Config *Config `do:""`
}
// Register services
do.Provide(injector, func(i do.Injector) (*Database, error) {
return &Database{}, nil
})
do.ProvideNamed(injector, "app-logger", func(i do.Injector) (*Logger, error) {
return &Logger{}, nil
})
do.Provide(injector, func(i do.Injector) (*Config, error) {
return &Config{}, nil
})
// Invoke struct with injected services (panics on error)
app := do.MustInvokeStruct[App](injector)
func MustShutdown ¶
MustShutdown stops a service, using type inference to determine the service name. It panics on error. This function performs a graceful shutdown on a service by inferring its name from the type T. If the shutdown fails, this function will panic.
Parameters:
- i: The injector containing the service
Panics if the shutdown fails.
Example:
do.MustShutdown[*Database](injector)
func MustShutdownNamed ¶
MustShutdownNamed stops a named service. It panics on error. This function performs a graceful shutdown on a service with the specified name. If the shutdown fails, this function will panic.
Parameters:
- i: The injector containing the service
- name: The name of the service to shutdown
Panics if the shutdown fails.
Example:
do.MustShutdownNamed(injector, "main-database")
func MustShutdownNamedWithContext ¶
MustShutdownNamedWithContext stops a named service. It panics on error. This function performs a graceful shutdown on a service with the specified name and context support for timeout and cancellation. If the shutdown fails, this function will panic.
Parameters:
- ctx: Context for cancellation and timeout control
- i: The injector containing the service
- name: The name of the service to shutdown
Panics if the shutdown fails.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() do.MustShutdownNamedWithContext(ctx, injector, "main-database")
func MustShutdownWithContext ¶
MustShutdownWithContext stops a service, using type inference to determine the service name. It panics on error. This function performs a graceful shutdown on a service with context support for timeout and cancellation. If the shutdown fails, this function will panic.
Parameters:
- ctx: Context for cancellation and timeout control
- i: The injector containing the service
Panics if the shutdown fails.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() do.MustShutdownWithContext[*Database](ctx, injector)
func NameOf ¶
NameOf returns the name of the service in the DI container. This is highly discouraged to use this function, as your code should not declare any dependency explicitly.
The function uses type inference to determine the service name based on the generic type parameter T.
Example:
serviceName := do.NameOf[*Database]()
func Override ¶
Override replaces the service in the DI container, using type inference to determine the service name. Warning: this will not unload/shutdown the previously invoked service.
This function is useful for testing or when you need to replace a service that has already been registered. However, be cautious as it may lead to resource leaks if the original service was already instantiated.
func OverrideNamed ¶
OverrideNamed replaces the named service in the DI container. Warning: this will not unload/shutdown the previously invoked service.
This function allows you to replace a specific named service that has already been registered. Use with caution to avoid resource leaks.
func OverrideNamedTransient ¶
OverrideNamedTransient replaces the named factory in the DI container. Warning: this will not unload/shutdown the previously invoked service.
This function allows you to replace a specific named transient service factory. Since transient services are recreated on each request, this is generally safer than overriding lazy or eager services.
func OverrideNamedValue ¶
OverrideNamedValue replaces the named value in the DI container. Warning: this will not unload/shutdown the previously invoked service.
This function allows you to replace a specific named value service. Use with caution to avoid resource leaks.
func OverrideTransient ¶
OverrideTransient replaces the factory in the DI container, using type inference to determine the service name. Warning: this will not unload/shutdown the previously invoked service.
This function replaces an existing transient service factory with a new one. Since transient services are recreated on each request, this is generally safer than overriding lazy or eager services.
func OverrideValue ¶
OverrideValue replaces the value in the DI container, using type inference to determine the service name. Warning: this will not unload/shutdown the previously invoked service.
This function replaces an existing value service with a new one. The old value will not be properly cleaned up if it was already instantiated.
func Package ¶
Package creates a function that executes multiple service registration functions. This function is used to group related service registrations into reusable packages that can be applied to any injector instance.
Parameters:
- services: Variable number of service registration functions to execute
Returns a function that can be passed to New(), NewWithOpts(), or Scope() to register all services.
Example:
// pkg/database/package.go
// Create a global `Package` variable
var Package = do.Package(
do.Lazy[*Database](func(i do.Injector) (*Database, error) {
return &Database{}, nil
}),
do.Lazy[*ConnectionPool](func(i do.Injector) (*ConnectionPool, error) {
return &ConnectionPool{}, nil
}),
...
)
// main.go
// Apply the package to an injector
injector := do.New(database.Package)
func Provide ¶
Provide registers a service in the DI container, using type inference. The service will be lazily instantiated when first requested.
Example:
do.Provide(injector, func(i do.Injector) (*MyService, error) {
return &MyService{...}, nil
})
func ProvideNamed ¶
ProvideNamed registers a named service in the DI container. This allows you to register multiple services of the same type with different names for disambiguation.
The service will be lazily instantiated when first requested.
Example:
do.ProvideNamed(injector, "main-db", func(i do.Injector) (*Database, error) {
return &Database{URL: "postgres://main.acme.dev:5432/db"}, nil
})
do.ProvideNamed(injector, "backup-db", func(i do.Injector) (*Database, error) {
return &Database{URL: "postgres://backup.acme.dev:5432/db"}, nil
})
func ProvideNamedTransient ¶
ProvideNamedTransient registers a named factory in the DI container. This allows you to register multiple transient services of the same type with different names for disambiguation.
The service will be recreated each time it is requested, providing a fresh instance.
Example:
// Each invocation creates a new instance
do.ProvideNamedTransient(injector, "request-id", func(i do.Injector) (string, error) {
return uuid.New().String(), nil
})
// First invocation
id1, _ := do.InvokeNamed[string](injector, "request-id")
// Second invocation - different instance
id2, _ := do.InvokeNamed[string](injector, "request-id")
fmt.Println(id1 != id2) // Output: true
func ProvideNamedValue ¶
ProvideNamedValue registers a named value in the DI container. This allows you to register multiple values of the same type with different names for disambiguation.
The value is immediately available and will not be recreated on each request.
Example:
do.ProvideNamedValue(injector, "app-config", &Config{Port: 8080})
do.ProvideNamedValue(injector, "db-config", &Config{Port: 5432})
func ProvideTransient ¶
ProvideTransient registers a factory in the DI container, using type inference to determine the service name. The service will be recreated each time it is requested, providing a fresh instance.
Example:
// Each invocation creates a new instance
do.ProvideTransient(injector, func(i do.Injector) (string, error) {
return uuid.New().String(), nil
})
// First invocation
id1, _ := do.Invoke[string](injector)
// Second invocation - different instance
id2, _ := do.Invoke[string](injector)
fmt.Println(id1 != id2) // Output: true
func ProvideValue ¶
ProvideValue registers a value in the DI container, using type inference to determine the service name. The value is immediately available and will not be recreated on each request.
Example:
ProvideValue(injector, &MyService{})
func Shutdown ¶
Shutdown stops a service, using type inference to determine the service name. This function performs a graceful shutdown on a service by inferring its name from the type T. The service must implement one of the Shutdowner interfaces.
Parameters:
- i: The injector containing the service
Returns an error if the shutdown fails, or nil if the shutdown was successful.
Example:
err := do.Shutdown[*Database](injector)
if err != nil {
log.Printf("Database shutdown failed: %v", err)
}
func ShutdownNamed ¶
ShutdownNamed stops a named service. This function performs a graceful shutdown on a service with the specified name. The service must implement one of the Shutdowner interfaces.
Parameters:
- i: The injector containing the service
- name: The name of the service to shutdown
Returns an error if the shutdown fails, or nil if the shutdown was successful.
Example:
err := do.ShutdownNamed(injector, "main-database")
if err != nil {
log.Printf("Main database shutdown failed: %v", err)
}
func ShutdownNamedWithContext ¶
ShutdownNamedWithContext stops a named service with context support. This function performs a graceful shutdown on a service with the specified name and context support for timeout and cancellation. The service must implement one of the Shutdowner interfaces.
Parameters:
- ctx: Context for cancellation and timeout control
- i: The injector containing the service
- name: The name of the service to shutdown
Returns an error if the shutdown fails, or nil if the shutdown was successful.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := do.ShutdownNamedWithContext(ctx, injector, "main-database")
if err != nil {
log.Printf("Main database shutdown failed: %v", err)
}
func ShutdownWithContext ¶
ShutdownWithContext stops a service, using type inference to determine the service name. This function performs a graceful shutdown on a service with context support for timeout and cancellation. The service must implement one of the Shutdowner interfaces.
Parameters:
- ctx: Context for cancellation and timeout control
- i: The injector containing the service
Returns an error if the shutdown fails, or nil if the shutdown was successful.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := do.ShutdownWithContext[*Database](ctx, injector)
if err != nil {
log.Printf("Database shutdown failed: %v", err)
}
func Transient ¶
Transient creates a function that registers a transient service using the default service name. This function is a convenience wrapper for creating transient service registration functions that can be used in packages.
Parameters:
- p: The provider function that creates the service instance
Returns a function that registers the service as transient when executed.
Example:
loggerService := do.Transient[*Logger](func(i do.Injector) (*Logger, error) {
return &Logger{}, nil
})
// Global to a package
var Package = do.Package(loggerService, ...)
func TransientNamed ¶
TransientNamed creates a function that registers a transient service with a custom name. This function is a convenience wrapper for creating named transient service registration functions that can be used in packages.
Parameters:
- serviceName: The custom name for the service
- p: The provider function that creates the service instance
Returns a function that registers the service as transient with the specified name when executed.
Example:
loggerService := do.TransientNamed[*Logger]("request-logger", func(i do.Injector) (*Logger, error) {
return &Logger{}, nil
})
// Global to a package
var Package = do.Package(loggerService, ...)
Types ¶
type DAG ¶
type DAG struct {
// contains filtered or unexported fields
}
DAG represents a Directed Acyclic Graph of services, tracking dependencies and dependents. This type manages the relationships between services to ensure proper initialization order and detect circular dependencies.
The DAG maintains two maps:
- dependencies: Maps each service to the services it depends on
- dependents: Maps each service to the services that depend on it
Fields:
- mu: Read-write mutex for thread-safe access to the graph
- dependencies: Map of services to their dependencies
- dependents: Map of services to their dependents
type ExplainInjectorOutput ¶
type ExplainInjectorOutput struct {
ScopeID string `json:"scope_id"`
ScopeName string `json:"scope_name"`
DAG []ExplainInjectorScopeOutput `json:"dag"`
}
ExplainInjectorOutput contains detailed information about an injector and its scope hierarchy. This struct provides a comprehensive view of the injector's scope tree, including all services and their relationships.
func ExplainInjector ¶
func ExplainInjector(scope Injector) ExplainInjectorOutput
ExplainInjector returns a human readable description of the injector, with services and scope tree. This function provides a comprehensive view of the injector's structure, including all scopes, services, and their relationships in a hierarchical format.
Parameters:
- scope: The injector to explain
Returns a detailed explanation of the injector's structure and contents.
Example:
explanation := do.ExplainInjector(injector) fmt.Println(explanation.String())
Output example:
Scope ID: root Scope name: Root Scope DAG: |\_ Root Scope (ID: root) | * 😴 Database | * 🔁 Config | |\_ API Scope (ID: api) | | * 🏭 Logger | | * 🔗 DatabaseInterface
func (*ExplainInjectorOutput) String ¶
func (id *ExplainInjectorOutput) String() string
String returns a formatted string representation of the injector explanation. This method provides a human-readable description of the injector including its scope hierarchy and all services in a tree-like format.
Returns a formatted string describing the injector and its scope hierarchy.
type ExplainInjectorScopeOutput ¶
type ExplainInjectorScopeOutput struct {
ScopeID string `json:"scope_id"`
ScopeName string `json:"scope_name"`
Scope Injector `json:"scope"`
Services []ExplainInjectorServiceOutput `json:"services"`
Children []ExplainInjectorScopeOutput `json:"children"`
IsAncestor bool `json:"is_ancestor"`
IsChildren bool `json:"is_children"`
}
ExplainInjectorScopeOutput contains information about a single scope in the injector hierarchy. This struct represents a scope and its services, along with its position in the scope tree.
func (*ExplainInjectorScopeOutput) String ¶
func (ids *ExplainInjectorScopeOutput) String() string
String returns a formatted string representation of the scope. This method provides a human-readable description of the scope including its services and child scopes.
Returns a formatted string describing the scope.
type ExplainInjectorServiceOutput ¶
type ExplainInjectorServiceOutput struct {
ServiceName string `json:"service_name"`
ServiceType ServiceType `json:"service_type"`
ServiceTypeIcon string `json:"service_type_icon"`
ServiceBuildTime time.Duration `json:"service_build_time,omitempty"`
IsHealthchecker bool `json:"is_healthchecker"`
IsShutdowner bool `json:"is_shutdowner"`
}
ExplainInjectorServiceOutput contains information about a service in the scope explanation. This struct provides details about a service's type, capabilities, and lifecycle state.
func (*ExplainInjectorServiceOutput) String ¶
func (idss *ExplainInjectorServiceOutput) String() string
String returns a formatted string representation of the service. This method provides a human-readable description of the service including its type icon and capabilities indicators.
Returns a formatted string describing the service.
type ExplainServiceDependencyOutput ¶
type ExplainServiceDependencyOutput struct {
ScopeID string `json:"scope_id"`
ScopeName string `json:"scope_name"`
Service string `json:"service"`
Recursive []ExplainServiceDependencyOutput `json:"recursive"`
}
ExplainServiceDependencyOutput contains information about a service dependency relationship. This struct represents either a dependency (service this depends on) or a dependent (service that depends on this) in the dependency graph.
Fields:
- ScopeID: The unique identifier of the scope containing the related service
- ScopeName: The human-readable name of the scope containing the related service
- Service: The name of the related service
- Recursive: Nested dependency relationships (for transitive dependencies)
func (*ExplainServiceDependencyOutput) String ¶
func (sdd *ExplainServiceDependencyOutput) String() string
String returns a formatted string representation of the dependency relationship. This method provides a human-readable description of the dependency, including nested recursive dependencies with proper indentation.
Returns a formatted string describing the dependency relationship.
type ExplainServiceOutput ¶
type ExplainServiceOutput struct {
ScopeID string `json:"scope_id"`
ScopeName string `json:"scope_name"`
ServiceName string `json:"service_name"`
ServiceType ServiceType `json:"service_type"`
ServiceBuildTime time.Duration `json:"service_build_time,omitempty"`
Invoked *stacktrace.Frame `json:"invoked"`
Dependencies []ExplainServiceDependencyOutput `json:"dependencies"`
Dependents []ExplainServiceDependencyOutput `json:"dependents"`
}
ExplainServiceOutput contains detailed information about a service for debugging and analysis. This struct provides comprehensive information about a service's location, type, dependencies, and lifecycle state.
func ExplainNamedService ¶
func ExplainNamedService(scope Injector, name string) (description ExplainServiceOutput, ok bool)
ExplainNamedService returns a human readable description of the service by name. This function provides detailed information about a service including its scope, type, dependencies, and lifecycle state. The service must be registered before calling this function.
Parameters:
- scope: The injector to search for the service
- name: The name of the service to explain
Returns a service explanation and a boolean indicating if the service was found. The boolean is false if the service is not found.
Note: Please call Invoke[T] before ExplainNamedService[T] to ensure that the service is registered.
Example:
// First invoke the service to ensure it's registered
db := do.MustInvokeNamed[*Database](injector, "main-db")
// Then explain it
explanation, found := do.ExplainNamedService(injector, "main-db")
if found {
fmt.Println(explanation.String())
}
func ExplainService ¶
func ExplainService[T any](i Injector) (description ExplainServiceOutput, ok bool)
ExplainService returns a human readable description of the service. This function provides detailed information about a service including its scope, type, dependencies, and lifecycle state. The service must be registered before calling this function.
Parameters:
- i: The injector to search for the service
Returns a service explanation and a boolean indicating if the service was found. The boolean is false if the service is not found.
Note: Please call Invoke[T] before ExplainService[T] to ensure that the service is registered.
Example:
// First invoke the service to ensure it's registered
db := do.MustInvoke[*Database](injector)
// Then explain it
explanation, found := do.ExplainService[*Database](injector)
if found {
fmt.Println(explanation.String())
}
func (*ExplainServiceOutput) String ¶
func (sd *ExplainServiceOutput) String() string
String returns a formatted string representation of the service explanation. This method provides a human-readable description of the service including its scope, type, build time, and dependency relationships.
Returns a formatted string describing the service.
type Healthchecker ¶
type Healthchecker interface {
HealthCheck() error
}
Healthchecker is an interface that services can implement to provide health checking capabilities. Services implementing this interface can be health-checked by the DI container to ensure they are functioning correctly.
The HealthCheck method should perform a quick check to verify the service is healthy. It should return nil if the service is healthy, or an error describing the health issue.
Example:
type Database struct {
conn *sql.DB
}
func (db *Database) HealthCheck() error {
return db.conn.Ping()
}
type HealthcheckerWithContext ¶
HealthcheckerWithContext is an interface that services can implement to provide health checking capabilities with context support. This allows for timeout and cancellation control during health checks.
The HealthCheck method should perform a quick check to verify the service is healthy. It should respect the provided context for cancellation and timeout. It should return nil if the service is healthy, or an error describing the health issue.
Example:
type Database struct {
conn *sql.DB
}
func (db *Database) HealthCheck(ctx context.Context) error {
return db.conn.PingContext(ctx)
}
type Injector ¶
type Injector interface {
// ID returns the unique identifier of the injector.
ID() string
// Name returns the human-readable name of the injector.
Name() string
// Scope creates a new child scope with the given name.
// Optional package functions can be provided to execute during scope creation.
Scope(string, ...func(Injector)) *Scope
// RootScope returns the root scope of the injector hierarchy.
RootScope() *RootScope
// Ancestors returns the list of all parent scopes in order from immediate parent to root.
Ancestors() []*Scope
// Children returns the list of immediate child scopes.
Children() []*Scope
// ChildByID searches for a child scope by its unique ID across the entire scope hierarchy.
ChildByID(string) (*Scope, bool)
// ChildByName searches for a child scope by its name across the entire scope hierarchy.
ChildByName(string) (*Scope, bool)
// ListProvidedServices returns all services available in the current scope and all its ancestor scopes.
ListProvidedServices() []ServiceDescription
// ListInvokedServices returns only the services that have been actually invoked in the current scope and its ancestors.
ListInvokedServices() []ServiceDescription
// HealthCheck performs health checks on all services in the current scope and its ancestors.
HealthCheck() map[string]error
// HealthCheckWithContext performs health checks with context support for cancellation and timeouts.
HealthCheckWithContext(context.Context) map[string]error
// Shutdown gracefully shuts down the injector and all its descendant scopes.
Shutdown() *ShutdownReport
// ShutdownWithContext gracefully shuts down the injector and all its descendant scopes with context support.
ShutdownWithContext(context.Context) *ShutdownReport
// contains filtered or unexported methods
}
Injector is the main interface for dependency injection containers. It provides methods for service registration, resolution, lifecycle management, and scope hierarchy management.
The Injector interface is implemented by both RootScope and Scope types, allowing for a consistent API across different levels of the scope hierarchy.
type InjectorOpts ¶
type InjectorOpts struct {
// HookBeforeRegistration is called before a service is registered in a scope.
// This hook can be used for validation, logging, or other pre-registration tasks.
HookBeforeRegistration []func(scope *Scope, serviceName string)
// HookAfterRegistration is called after a service is successfully registered in a scope.
// This hook can be used for logging, metrics collection, or other post-registration tasks.
HookAfterRegistration []func(scope *Scope, serviceName string)
// HookBeforeInvocation is called before a service is invoked (instantiated).
// This hook can be used for logging, metrics, or other pre-invocation tasks.
HookBeforeInvocation []func(scope *Scope, serviceName string)
// HookAfterInvocation is called after a service is invoked, with the result error.
// This hook can be used for logging, metrics collection, or error handling.
HookAfterInvocation []func(scope *Scope, serviceName string, err error)
// HookBeforeShutdown is called before a service is shut down.
// This hook can be used for cleanup preparation or logging.
HookBeforeShutdown []func(scope *Scope, serviceName string)
// HookAfterShutdown is called after a service is shut down, with the result error.
// This hook can be used for logging, metrics collection, or error handling.
HookAfterShutdown []func(scope *Scope, serviceName string, err error)
// Logf is the logging function used by the DI container for internal logging.
// If not provided, no logging will occur. This function should handle the format
// string and arguments similar to fmt.Printf.
Logf func(format string, args ...any)
// HealthCheckParallelism controls the number of concurrent health checks that can run simultaneously.
// Default: all health checks run in parallel (unlimited).
// Setting this to a positive number limits the concurrency for better resource management.
HealthCheckParallelism uint
// HealthCheckGlobalTimeout sets a global timeout for all health check operations.
// This timeout applies to the entire health check process across all services.
// Default: no timeout (health checks can run indefinitely).
HealthCheckGlobalTimeout time.Duration
// HealthCheckTimeout sets a timeout for individual service health checks.
// This timeout applies to each service's health check method.
// Default: no timeout (individual health checks can run indefinitely).
HealthCheckTimeout time.Duration
// StructTagKey specifies the tag key used for struct field injection.
// Default: "do" (see DefaultStructTagKey constant).
// This allows customization of the struct tag format for injection.
StructTagKey string
}
InjectorOpts contains all configuration options for the dependency injection container. These options control logging, hooks, health checks, and other behavioral aspects of the DI container.
type Provider ¶
Provider is a function type that creates and returns a service instance of type T. This is the core abstraction for service creation in the dependency injection container.
The provider function receives an Injector instance that can be used to resolve dependencies for the service being created.
Example:
func NewMyService(i do.Injector) (*MyService, error) {
db := do.MustInvoke[*Database](i)
config := do.MustInvoke[*Config](i)
return &MyService{DB: db, Config: config}, nil
}
// Register the provider
do.Provide(injector, NewMyService)
type RootScope ¶
type RootScope struct {
// contains filtered or unexported fields
}
RootScope is the top-level scope in the dependency injection container hierarchy. It serves as the entry point for all DI operations and manages the overall container lifecycle.
Key responsibilities:
- Service registration and resolution
- Child scope management
- Health check coordination
- Shutdown orchestration
- Dependency graph management
func New ¶
New creates a new dependency injection container with default options. This is the primary entry point for creating a new DI container.
Parameters:
- packages: Optional package functions to execute during initialization
Returns a new RootScope instance ready for service registration.
Example:
injector := do.New()
do.Provide(injector, func(i do.Injector) (*MyService, error) {
return &MyService{}, nil
})
func NewWithOpts ¶
func NewWithOpts(opts *InjectorOpts, packages ...func(Injector)) *RootScope
NewWithOpts creates a new dependency injection container with custom options. This allows you to configure logging, hooks, health check settings, and other options.
Parameters:
- opts: Configuration options for the injector
- packages: Optional package functions to execute during initialization
Returns a new RootScope instance with the specified configuration.
Example:
opts := &do.InjectorOpts{
Logf: func(format string, args ...any) {
log.Printf(format, args...)
},
HealthCheckParallelism: 10,
}
injector := do.NewWithOpts(opts)
func (*RootScope) AddAfterInvocationHook ¶
AddAfterInvocationHook adds a hook that will be called after a service is invoked.
func (*RootScope) AddAfterRegistrationHook ¶
AddAfterRegistrationHook adds a hook that will be called after a service is registered.
func (*RootScope) AddAfterShutdownHook ¶
AddAfterShutdownHook adds a hook that will be called after a service is shutdown.
func (*RootScope) AddBeforeInvocationHook ¶
AddBeforeInvocationHook adds a hook that will be called before a service is invoked.
func (*RootScope) AddBeforeRegistrationHook ¶
AddBeforeRegistrationHook adds a hook that will be called before a service is registered.
func (*RootScope) AddBeforeShutdownHook ¶
AddBeforeShutdownHook adds a hook that will be called before a service is shutdown.
func (*RootScope) Ancestors ¶
Ancestors returns an empty slice since the root scope has no ancestors.
func (*RootScope) ChildByID ¶
ChildByID searches for a child scope by its unique ID across the entire scope hierarchy.
func (*RootScope) ChildByName ¶
ChildByName searches for a child scope by its name across the entire scope hierarchy.
func (*RootScope) Clone ¶
Clone clones injector with provided services but not with invoked instances.
func (*RootScope) CloneWithOpts ¶
func (s *RootScope) CloneWithOpts(opts *InjectorOpts) *RootScope
CloneWithOpts clones injector with provided services but not with invoked instances, with options.
func (*RootScope) HealthCheck ¶
HealthCheck performs health checks on all services in the root scope and all its descendant scopes.
func (*RootScope) HealthCheckWithContext ¶
HealthCheckWithContext performs health checks with context support for cancellation and timeouts.
func (*RootScope) ListInvokedServices ¶
func (s *RootScope) ListInvokedServices() []ServiceDescription
ListInvokedServices returns all services that have been invoked in the root scope and all its descendant scopes.
func (*RootScope) ListProvidedServices ¶
func (s *RootScope) ListProvidedServices() []ServiceDescription
ListProvidedServices returns all services available in the root scope and all its descendant scopes.
func (*RootScope) Shutdown ¶
func (s *RootScope) Shutdown() *ShutdownReport
Shutdown gracefully shuts down the root scope and all its descendant scopes.
func (*RootScope) ShutdownOnSignals ¶
ShutdownOnSignals listens for the provided signals in order to gracefully stop services. It will block until receiving any of these signals. If no signal is provided, syscall.SIGTERM and os.Interrupt will be handled by default.
func (*RootScope) ShutdownOnSignalsWithContext ¶
func (s *RootScope) ShutdownOnSignalsWithContext(ctx context.Context, signals ...os.Signal) (os.Signal, *ShutdownReport)
ShutdownOnSignalsWithContext listens for the provided signals in order to gracefully stop services. It will block until receiving any of these signals. If no signal is provided, syscall.SIGTERM and os.Interrupt will be handled by default.
func (*RootScope) ShutdownWithContext ¶
func (s *RootScope) ShutdownWithContext(ctx context.Context) *ShutdownReport
ShutdownWithContext gracefully shuts down the root scope and all its descendant scopes with context support. This method ensures proper cleanup of the health check pool and all registered services.
type Scope ¶
type Scope struct {
// contains filtered or unexported fields
}
Scope represents a dependency injection container that can contain services and child scopes. Scopes form a hierarchical tree structure where child scopes can access services from their parent scopes, but not vice versa.
Key features:
- Hierarchical service resolution (child scopes can access parent services)
- Isolated service registration (services in child scopes don't affect parents)
- Thread-safe operations
- Service lifecycle management (health checks, shutdown)
- Observability and debugging support
func (*Scope) Ancestors ¶
Ancestors returns the list of all parent scopes in order from immediate parent to root. This is useful for understanding the scope hierarchy and for operations that need to traverse up the scope tree.
Returns an empty slice for the root scope, and a slice of parent scopes for child scopes, ordered from immediate parent to root.
func (*Scope) ChildByID ¶
ChildByID searches for a child scope by its unique ID across the entire scope hierarchy. This method performs a recursive search through all descendant scopes.
Parameters:
- id: The unique ID of the scope to find
Returns the found scope and true if found, or nil and false if not found.
func (*Scope) ChildByName ¶
ChildByName searches for a child scope by its name across the entire scope hierarchy. This method performs a recursive search through all descendant scopes.
Parameters:
- name: The name of the scope to find
Returns the found scope and true if found, or nil and false if not found.
func (*Scope) Children ¶
Children returns the list of immediate child scopes. This method only returns direct children, not grandchildren or deeper descendants.
Returns a slice of child scopes. The order is not guaranteed to be stable.
func (*Scope) HealthCheck ¶
HealthCheck performs health checks on all services in the current scope and its ancestors that implement the Healthchecker interface.
Returns a map of service names to error values. A nil error indicates a successful health check.
func (*Scope) HealthCheckWithContext ¶
HealthCheckWithContext performs health checks on all services in the current scope and its ancestors that implement the Healthchecker interface, with context support for cancellation and timeouts.
Parameters:
- ctx: Context for cancellation and timeout control
Returns a map of service names to error values. A nil error indicates a successful health check.
func (*Scope) ID ¶
ID returns the unique identifier of the scope. This ID is generated using UUID and is immutable throughout the scope's lifetime.
func (*Scope) ListInvokedServices ¶
func (s *Scope) ListInvokedServices() []ServiceDescription
ListInvokedServices returns only the services that have been actually invoked (instantiated) in the current scope and its ancestors. This is useful for understanding which services are actually being used and for debugging dependency issues.
Returns a slice of ServiceDescription objects representing only the invoked services.
func (*Scope) ListProvidedServices ¶
func (s *Scope) ListProvidedServices() []ServiceDescription
ListProvidedServices returns all services available in the current scope and all its ancestor scopes. This provides a complete view of the service hierarchy, showing all services that can be accessed from the current scope.
Returns a slice of ServiceDescription objects representing all available services, including those inherited from parent scopes.
func (*Scope) Name ¶
Name returns the human-readable name of the scope. This name is provided when creating the scope and is immutable.
func (*Scope) RootScope ¶
RootScope returns the root scope of the scope hierarchy. All scopes in a hierarchy share the same root scope, regardless of their depth.
func (*Scope) Scope ¶
Scope creates a new child scope with the given name. Child scopes inherit access to services from their parent scopes, but services registered in child scopes are not accessible to parents.
Parameters:
- name: The name for the new child scope (must be unique within the parent)
- packages: Optional package functions to execute in the new scope
Returns the newly created child scope.
Panics if a scope with the same name already exists in the parent.
func (*Scope) Shutdown ¶
func (s *Scope) Shutdown() *ShutdownReport
Shutdown gracefully shuts down the scope and all its children. This method calls ShutdownWithContext with a background context.
Returns a ShutdownReport containing any errors and timings that occurred during shutdown.
func (*Scope) ShutdownWithContext ¶
func (s *Scope) ShutdownWithContext(ctx context.Context) *ShutdownReport
ShutdownWithContext gracefully shuts down the scope and all its children with context support. This method performs shutdown operations in parallel for better performance.
Parameters:
- ctx: Context for cancellation and timeout control
Returns a ShutdownReport containing any errors and timings that occurred during shutdown.
type ServiceDescription ¶
ServiceDescription represents a service in the dependency graph (DAG), identified by scope ID, scope name, and service name. This type is used to uniquely identify services across the entire scope hierarchy for dependency tracking.
Fields:
- ScopeID: The unique identifier of the scope containing the service
- ScopeName: The human-readable name of the scope containing the service
- Service: The name of the service within the scope
type ServiceType ¶
type ServiceType string
ServiceType represents the different types of services that can be registered in the dependency injection container. Each type has different lifecycle and instantiation behavior.
const ( // ServiceTypeLazy represents a service that is instantiated only when first requested. // The service instance is cached and reused for subsequent requests. ServiceTypeLazy ServiceType = "lazy" // ServiceTypeEager represents a service that is instantiated immediately when registered. // The service is always available and ready to use. ServiceTypeEager ServiceType = "eager" // ServiceTypeTransient represents a service that is recreated each time it is requested. // No singleton caching is performed, ensuring a fresh instance every time. It is basically a factory. ServiceTypeTransient ServiceType = "transient" // ServiceTypeAlias represents a service that is an alias to another service. // It provides a different interface or name for accessing an existing service. ServiceTypeAlias ServiceType = "alias" )
type ShutdownReport ¶
type ShutdownReport struct {
Succeed bool
Services []ServiceDescription
Errors map[ServiceDescription]error
ShutdownTime time.Duration
ServiceShutdownTime map[ServiceDescription]time.Duration
}
ShutdownReport represents the result of a shutdown operation. It includes overall success, the list of services that were shut down, any errors encountered, total shutdown time, and per-service shutdown durations.
It implements the error interface, returning a formatted description of errors when any occurred, or a "no shutdown errors" message otherwise.
func (ShutdownReport) Error ¶
func (r ShutdownReport) Error() string
Error implements the error interface for ShutdownReport. If there are errors, it returns a multiline description. Otherwise a friendly message.
type Shutdowner ¶
type Shutdowner interface {
Shutdown()
}
Shutdowner is an interface that services can implement to provide graceful shutdown capabilities. Services implementing this interface will be called during container shutdown to perform cleanup operations.
The Shutdown method should perform any necessary cleanup, such as closing connections, flushing buffers, or stopping background processes.
Example:
type Logger struct {
file *os.File
}
func (l *Logger) Shutdown() {
l.file.Close()
}
type ShutdownerWithContext ¶
ShutdownerWithContext is an interface that services can implement to provide graceful shutdown capabilities with context support. This allows for timeout and cancellation control during shutdown operations.
The Shutdown method should perform any necessary cleanup and respect the provided context for cancellation and timeout.
Example:
type Server struct {
srv *http.Server
}
func (s *Server) Shutdown(ctx context.Context) {
s.srv.Shutdown(ctx)
}
type ShutdownerWithContextAndError ¶
ShutdownerWithContextAndError is an interface that services can implement to provide graceful shutdown capabilities with both context support and error reporting. This is the most flexible shutdown interface, allowing for timeout control and error reporting.
The Shutdown method should perform any necessary cleanup, respect the provided context for cancellation and timeout, and return an error if the shutdown process fails.
Example:
type Server struct {
srv *http.Server
}
func (s *Server) Shutdown(ctx context.Context) error {
return s.srv.Shutdown(ctx)
}
type ShutdownerWithError ¶
type ShutdownerWithError interface {
Shutdown() error
}
ShutdownerWithError is an interface that services can implement to provide graceful shutdown capabilities with error reporting. This allows services to report any errors that occur during shutdown.
The Shutdown method should perform any necessary cleanup and return an error if the shutdown process fails.
Example:
type Database struct {
conn *sql.DB
}
func (db *Database) Shutdown() error {
return db.conn.Close()
}