dix

dix is a lightweight yet powerful dependency injection framework for Go.
Inspired by uber-go/dig, with support for advanced dependency management and namespace isolation.
ไธญๆๆๆกฃ
โจ Features
| Feature |
Description |
| ๐ Cycle Detection |
Auto-detect dependency cycles |
| ๐ฆ Multiple Injection |
Support func, struct, map, list |
| ๐ท๏ธ Namespace |
Dependency isolation via map key |
| ๐ฏ Multi-Output |
Struct can provide multiple dependencies |
| ๐ช Nested Support |
Support nested struct injection |
| ๐ง Non-Invasive |
Zero intrusion to original objects |
| ๐ก๏ธ Safe API |
TryProvide/TryInject won't panic |
| ๐ Visualization |
HTTP module for dependency graph |
๐ฆ Installation
go get github.com/pubgo/dix/v2
๐ Quick Start
package main
import (
"fmt"
"github.com/pubgo/dix/v2"
)
type Config struct {
DSN string
}
type Database struct {
Config *Config
}
type UserService struct {
DB *Database
}
func main() {
// Create container
di := dix.New()
// Register Providers
dix.Provide(di, func() *Config {
return &Config{DSN: "postgres://localhost/mydb"}
})
dix.Provide(di, func(c *Config) *Database {
return &Database{Config: c}
})
dix.Provide(di, func(db *Database) *UserService {
return &UserService{DB: db}
})
// Inject and use
dix.Inject(di, func(svc *UserService) {
fmt.Println("DSN:", svc.DB.Config.DSN)
})
}
๐ Core API
Provide / TryProvide
Register constructor (Provider) to container:
// Standard version - panics on error
dix.Provide(di, func() *Service { return &Service{} })
// Safe version - returns error
err := dix.TryProvide(di, func() *Service { return &Service{} })
if err != nil {
log.Printf("Registration failed: %v", err)
}
Inject / TryInject
Inject dependencies from container:
// Function injection
dix.Inject(di, func(svc *Service) {
svc.DoSomething()
})
// Struct injection
type App struct {
Service *Service
Config *Config
}
app := &App{}
dix.Inject(di, app)
// Safe version
err := dix.TryInject(di, func(svc *Service) {
// ...
})
Startup Timeout / Slow Provider Warning
Control long-running providers during startup:
- Default provider timeout:
15s
- Disable provider timeout explicitly:
dix.WithProviderTimeout(0)
- Default slow provider warning threshold:
2s
- Disable slow provider warning:
dix.WithSlowProviderThreshold(0)
di := dix.New(
// Default `ProviderTimeout` is `15s`
// Use `dix.WithProviderTimeout(0)` to disable provider timeout
// Default `SlowProviderThreshold` is `2s`
// Use `dix.WithSlowProviderThreshold(0)` to disable slow-provider warnings
dix.WithProviderTimeout(2*time.Second), // override default (default: 15s, 0 = disabled)
dix.WithSlowProviderThreshold(300*time.Millisecond), // override default (default: 2s, 0 = disabled)
)
DI Trace Logging (Optional)
Enable step-by-step dependency resolution/injection/provider execution logs:
- Env var:
DIX_TRACE_DI
- Default: disabled
- Enable values:
1, true, on, yes, enable, trace, debug
export DIX_TRACE_DI=true
When enabled, dix prints di_trace ... events with structured key-values (provider, input/output types, query kind, parent chain, timeout, etc.).
Note: if DIX_LLM_DIAG_MODE=machine, human-readable text logs are suppressed by design, including di_trace lines.
Diagnostic File Collection (Optional)
You can collect detailed diagnostics into a searchable JSONL file:
- Env var:
DIX_DIAG_FILE
- Example:
export DIX_DIAG_FILE=.local/dix-diag.jsonl
Behavior rules:
- If
DIX_DIAG_FILE is not configured, dix keeps the original behavior (no diagnostic file output).
- If
DIX_DIAG_FILE is configured, dix appends diagnostic records to file (trace / error / llm).
- Console verbosity still follows existing controls (
DIX_TRACE_DI, DIX_LLM_DIAG_MODE).
Tip:
- Keep console output concise for users.
- Keep detailed records in file for search/LLM/offline troubleshooting.
In-Memory Trace Query (dixtrace, Optional)
Starting from this version, dix also emits unified trace events into an in-memory trace store (dixtrace), which can be queried via HTTP API (/api/trace).
- Default: enabled (in-memory ring buffer)
- Optional file sink env var:
DIX_TRACE_FILE
- Example:
export DIX_TRACE_FILE=.local/dix-trace.jsonl
- Compatibility fallback: when
DIX_TRACE_FILE is not set and DIX_DIAG_FILE is set, trace file sink will reuse DIX_DIAG_FILE in append mode.
/api/trace is optimized for online troubleshooting (filter by operation/status/event/component/provider/output_type).
If you need separate trace-only file persistence, set DIX_TRACE_FILE explicitly.
Quick event dictionary:
| Event |
Meaning |
di_trace inject.start |
Begin an injection request (component, param_type) |
di_trace inject.route |
Injection route selected (function or struct) |
di_trace provide.start |
Begin a provider registration request (component) |
di_trace provide.signature |
Provider function signature analyzed (input_count, output_count) |
di_trace provide.register.output.done |
Provider output type registered successfully |
di_trace provide.register.failed |
Provider registration failed (reason or error) |
di_trace resolve.value.search_provider.start |
Start searching providers for a dependency type |
di_trace resolve.value.found |
Dependency value resolved successfully |
di_trace resolve.value.not_found |
Dependency resolution failed (reason included) |
di_trace provider.execute.dispatch |
Provider selected for execution (provider, output_type, input_types) |
di_trace provider.input.resolve.start |
Resolve one provider input type |
di_trace provider.input.resolve.found |
Provider input resolved |
di_trace provider.input.resolve.failed |
Provider input resolution failed |
di_trace provider.call.start |
Start executing provider (timeout) |
di_trace provider.call.done |
Provider execution completed |
di_trace provider.call.failed |
Provider execution failed (timed_out, error) |
di_trace provider.call.return_error |
Provider returned non-nil error |
di_trace inject.func.resolve_input.start |
Resolve function injection argument |
di_trace inject.func.resolve_input.failed |
Function argument resolution failed |
di_trace inject.struct.field.resolve.start |
Resolve one struct field injection |
di_trace inject.struct.field.resolve.done |
Struct field injected successfully |
di_trace inject.struct.field.resolve.failed |
Struct field injection failed |
๐ฏ Injection Patterns
Struct Injection
type In struct {
Config *Config
Database *Database
}
type Out struct {
UserSvc *UserService
OrderSvc *OrderService
}
// Multiple inputs and outputs
dix.Provide(di, func(in In) Out {
return Out{
UserSvc: &UserService{DB: in.Database},
OrderSvc: &OrderService{DB: in.Database},
}
})
Map Injection (Namespace)
// Provide with namespace
dix.Provide(di, func() map[string]*Database {
return map[string]*Database{
"master": &Database{DSN: "master-dsn"},
"slave": &Database{DSN: "slave-dsn"},
}
})
// Inject specific namespace
dix.Inject(di, func(dbs map[string]*Database) {
master := dbs["master"]
slave := dbs["slave"]
})
List Injection
// Provide same type multiple times
dix.Provide(di, func() []Handler {
return []Handler{&AuthHandler{}}
})
dix.Provide(di, func() []Handler {
return []Handler{&LogHandler{}}
})
// Inject all
dix.Inject(di, func(handlers []Handler) {
// handlers contains AuthHandler and LogHandler
})
๐งฉ Modules
dixglobal - Global Container
Provides global singleton container for simple applications:
import "github.com/pubgo/dix/v2/dixglobal"
// Use directly without creating container
dixglobal.Provide(func() *Config { return &Config{} })
dixglobal.Inject(func(c *Config) { /* ... */ })
dixcontext - Context Integration
Bind container to context.Context:
import "github.com/pubgo/dix/v2/dixcontext"
// Store in context
ctx := dixcontext.Create(context.Background(), di)
// Retrieve and use
container := dixcontext.Get(ctx)
dixhttp - Dependency Visualization ๐
Web interface for visualizing dependency graph, designed for large projects:
import (
"github.com/pubgo/dix/v2/dixhttp"
"github.com/pubgo/dix/v2/dixinternal"
)
server := dixhttp.NewServer((*dixinternal.Dix)(di))
server.ListenAndServe(":8080")
Visit http://localhost:8080 to view dependency graph.
Highlights:
- ๐ Fuzzy Search - Quickly locate types or functions
- ๐ฆ Package Grouping - Collapsible sidebar browsing
- ๐ Bidirectional Tracking - Show both dependencies and dependents
- ๐ Depth Control - Limit display levels (1-5 or all)
- ๐จ Modern UI - Tailwind CSS + Alpine.js
See dixhttp/README.md for details.
๐ ๏ธ Development
# Run tests
task test
# Lint
task lint
# Build
task build
๐ Examples
๐ Documentation
๐ License
MIT