Skip to content

Repository files navigation

dix

Go ReferenceGo Report Card

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.

中文文档

Table of Contents

When to use dix

  • You need runtime dependency registration (plugins, dynamic modules, conditional wiring).
  • You want built-in diagnostics: structured trace logs, JSONL export, and an HTTP dependency graph.
  • You prefer a dig-like API with safe Try* variants, map/list grouping, and method injection.

For compile-time wiring with minimal runtime overhead, see google/wire. For Uber's fx ecosystem, see uber-go/dig.

✨ Features

FeatureDescription
🔄 Cycle DetectionAuto-detect dependency cycles
📦 Multiple InjectionSupport func, struct, map, list
🏷️ NamespaceDependency isolation via map key
🎯 Multi-OutputStruct can provide multiple dependencies
🪆 Nested SupportSupport nested struct injection
🔧 Non-InvasiveZero intrusion to original objects
🛡️ Safe APITryProvide/TryInject won't panic
🌐 VisualizationHTTP module for dependency graph

📦 Installation

go get github.com/pubgo/dix/v2

🚀 Quick Start

package main
import (
"fmt""github.com/pubgo/dix/v2"
)
typeConfigstruct {
DSNstring
}
typeDatabasestruct {
Config*Config
}
typeUserServicestruct {
DB*Database
}
funcmain() {
// Create containerdi:=dix.New()
// Register Providersdix.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 usedix.Inject(di, func(svc*UserService) {
fmt.Println("DSN:", svc.DB.Config.DSN)
})
}

For production startup, prefer TryProvide / TryInject to avoid panics and keep the process alive for diagnostics:

iferr:=dix.TryProvide(di, NewDatabase); err!=nil {
log.Fatal(err)
}
iferr:=dix.TryInject(di, Run); err!=nil {
log.Fatal(err)
}

📖 Core API

APIPanics on errorDescription
New(...Option)Create a container
Provide(di, fn)yesRegister a provider
TryProvide(di, fn)noRegister a provider, returns error
Inject(di, target)yesInject into a function or struct
TryInject(di, target)noInject, returns error
InjectT[T](di)yesAllocate a struct and inject exported fields
InjectTContext[T](ctx, di)yesAllocate a struct and inject with trace context
InjectContext / TryInjectContextyes / noInject with trace context propagation
Version()Return embedded version string

Container options:

OptionDefaultDescription
WithValuesNull()enabledAllow nil provider results
WithProviderTimeout(d)15sPer-provider execution timeout (0 = disabled)
WithSlowProviderThreshold(d)2sWarn when provider is slow (0 = disabled)

Provide / TryProvide

Register constructor (Provider) to container:

// Standard version - panics on errordix.Provide(di, func() *Service { return&Service{} })
// Safe version - returns errorerr:=dix.TryProvide(di, func() *Service { return&Service{} })
iferr!=nil {
log.Printf("Registration failed: %v", err)
}

Inject / TryInject

Inject dependencies from container:

// Function injectiondix.Inject(di, func(svc*Service) {
svc.DoSomething()
})
// Struct injectiontypeAppstruct {
Service*ServiceConfig*Config
}
app:=&App{}
dix.Inject(di, app)
// Safe versionerr:=dix.TryInject(di, func(svc*Service) {
// ...
})

Generic Helpers

// Inject into a new struct valueapp:= dix.InjectT[App](di)
// Inject with request-scoped trace contexterr:=dix.TryInjectContext(ctx, di, func(svc*Service) {
svc.DoSomething()
})

Thread Safety

Dix containers are not thread-safe. Do not call Provide / Inject (or their Try* variants) concurrently on the same container instance.

Recommended usage:

  • Register all providers during application startup (single goroutine).
  • After startup, only read resolved dependencies, or continue injection from a single goroutine.
  • Use separate Dix instances per goroutine if you need isolated containers.
  • For a process-wide singleton, prefer dixglobal only when startup is single-threaded.

Startup Options

di:=dix.New(
dix.WithProviderTimeout(2*time.Second), // default: 15s; 0 disablesdix.WithSlowProviderThreshold(300*time.Millisecond), // default: 2s; 0 disables
)

🎯 Injection Patterns

Struct Injection

typeInstruct {
Config*ConfigDatabase*Database
}
typeOutstruct {
UserSvc*UserServiceOrderSvc*OrderService
}
// Multiple inputs and outputsdix.Provide(di, func(inIn) Out {
returnOut{
UserSvc: &UserService{DB: in.Database},
OrderSvc: &OrderService{DB: in.Database},
}
})

Map Injection (Namespace)

// Provide with namespacedix.Provide(di, func() map[string]*Database {
returnmap[string]*Database{
"master": &Database{DSN: "master-dsn"},
"slave": &Database{DSN: "slave-dsn"},
}
})
// Inject specific namespacedix.Inject(di, func(dbsmap[string]*Database) {
master:=dbs["master"]
slave:=dbs["slave"]
})

List Injection

// Provide same type multiple timesdix.Provide(di, func() []Handler {
return []Handler{&AuthHandler{}}
})
dix.Provide(di, func() []Handler {
return []Handler{&LogHandler{}}
})
// Inject alldix.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 containerdixglobal.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 contextctx:=dixcontext.Create(context.Background(), di)
// Retrieve and usecontainer:=dixcontext.Get(ctx)
// Non-panicking lookupcontainer=dixcontext.GetOrNil(ctx)

dixhttp - Dependency Visualization

Web interface for visualizing dependency graphs, 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 the dependency graph.

Security: exposes dependency graphs, provider source locations, runtime errors, and trace data. Use on localhost or private networks only. Do not expose publicly without authentication.

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 API routes, event dictionary, and UI details.

🔍 Diagnostics

Optional observability for startup and injection troubleshooting. All file/console outputs are disabled unless configured.

Env varDefaultPurpose
DIX_TRACE_DIoffConsole step-by-step DI trace (di_trace ...)
DIX_DIAG_FILEoffAppend trace / error / llm records to JSONL
DIX_TRACE_FILEoffAppend trace-only JSONL (falls back to DIX_DIAG_FILE)
DIX_LLM_DIAG_MODEhumanLog mode: human / machine / dual
export DIX_TRACE_DI=true
export DIX_DIAG_FILE=.local/dix-diag.jsonl

In-memory trace events (dixtrace) are enabled by default and queryable through dixhttp at /api/trace.

For the full di_trace event dictionary, HTTP APIs, and UI troubleshooting workflow, see dixhttp/README.md.

🛠️ Development

# Run all tests with coverage report
task test# Lint and format
task lint
# go vet
task vet
# HTTP visualization demo
task web-demo

GitHub Actions runs go test ./... -race and golangci-lint on push/PR.

📚 Examples

ExampleDescription
struct-inStruct input injection
struct-outStruct multi-output
funcFunction injection
mapMap/namespace injection
map-nilMap with nil handling
listList injection
list-nilList with nil handling
lazyLazy injection
cycleCycle detection example
handlerHandler pattern
inject_methodMethod injection
test-return-errorError handling
httpHTTP visualization

📖 Documentation

DocumentDescription
Design DocumentArchitecture and detailed design
Audit ReportProject audit, evaluation and comparison
dixhttp READMEHTTP visualization module documentation

📄 License

MIT

About

A dependency injection tool that refers to the excellent design of dig

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages