{"id":50916421,"url":"https://github.com/quinnjr/go-dependency-injector","last_synced_at":"2026-06-16T15:32:16.648Z","repository":{"id":328804975,"uuid":"1115931732","full_name":"quinnjr/go-dependency-injector","owner":"quinnjr","description":"A lightweight, type-safe dependency injection (DI) and IoC container for Go. Features: generics, constructor injection, singleton/transient/scoped lifetimes, automatic resolution, thread-safe.","archived":false,"fork":false,"pushed_at":"2026-04-15T18:52:08.000Z","size":169,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-15T20:33:30.361Z","etag":null,"topics":["constructor-injection","constructor-injector","dependency-injection","dependency-management","di","di-container","generics","go","golang","inversion-of-control","inversion-of-control-container","ioc","service-container"],"latest_commit_sha":null,"homepage":"https://quinnjr.github.io/go-dependency-injector/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quinnjr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["quinnjr"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-12-13T21:05:40.000Z","updated_at":"2026-04-15T18:52:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/quinnjr/go-dependency-injector","commit_stats":null,"previous_names":["pegasusheavy/go-dependency-injector","quinnjr/go-dependency-injector"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/quinnjr/go-dependency-injector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quinnjr%2Fgo-dependency-injector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quinnjr%2Fgo-dependency-injector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quinnjr%2Fgo-dependency-injector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quinnjr%2Fgo-dependency-injector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quinnjr","download_url":"https://codeload.github.com/quinnjr/go-dependency-injector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quinnjr%2Fgo-dependency-injector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34412788,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constructor-injection","constructor-injector","dependency-injection","dependency-management","di","di-container","generics","go","golang","inversion-of-control","inversion-of-control-container","ioc","service-container"],"created_at":"2026-06-16T15:32:15.957Z","updated_at":"2026-06-16T15:32:16.640Z","avatar_url":"https://github.com/quinnjr.png","language":"Go","funding_links":["https://github.com/sponsors/quinnjr"],"categories":[],"sub_categories":[],"readme":"# Go Dependency Injector\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/pegasusheavy/go-dependency-injector.svg)](https://pkg.go.dev/github.com/pegasusheavy/go-dependency-injector)\n[![Go Report Card](https://goreportcard.com/badge/github.com/pegasusheavy/go-dependency-injector)](https://goreportcard.com/report/github.com/pegasusheavy/go-dependency-injector)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Go Version](https://img.shields.io/github/go-mod/go-version/pegasusheavy/go-dependency-injector)](https://github.com/pegasusheavy/go-dependency-injector)\n\nA lightweight, type-safe **dependency injection (DI) container** and **IoC (Inversion of Control)** framework for Go. This service container leverages Go generics for compile-time safety, automatic constructor injection, and a clean, intuitive API.\n\n**Keywords**: dependency injection, DI, IoC, inversion of control, service container, service locator, dependency container, golang DI, go dependency injection, constructor injection\n\n## Features\n\n- **Type-safe generics** — Compile-time type checking with `Register[T]()` and `Resolve[T]()`\n- **Multiple lifetimes** — Transient, Singleton, and Scoped dependency management\n- **Automatic resolution** — Constructor parameters are automatically resolved from the container\n- **Circular dependency detection** — Fails fast with clear error messages\n- **Named registrations** — Register multiple implementations of the same interface\n- **Thread-safe** — Safe for concurrent access across goroutines\n- **Zero external dependencies** — Uses only the Go standard library\n\n## Installation\n\n```bash\ngo get github.com/pegasusheavy/go-dependency-injector\n```\n\n## Quick Start\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/pegasusheavy/go-dependency-injector/di\"\n)\n\n// Define interfaces\ntype Logger interface {\n    Log(message string)\n}\n\ntype UserService interface {\n    GetUser(id int) string\n}\n\n// Implement them\ntype ConsoleLogger struct{}\n\nfunc (l *ConsoleLogger) Log(message string) {\n    fmt.Println(\"[LOG]\", message)\n}\n\ntype DefaultUserService struct {\n    logger Logger\n}\n\nfunc (s *DefaultUserService) GetUser(id int) string {\n    s.logger.Log(fmt.Sprintf(\"Fetching user %d\", id))\n    return fmt.Sprintf(\"User-%d\", id)\n}\n\nfunc main() {\n    // Create container\n    container := di.New()\n\n    // Register dependencies\n    di.Register[Logger](container, func() Logger {\n        return \u0026ConsoleLogger{}\n    }, di.AsSingleton())\n\n    di.Register[UserService](container, func(log Logger) UserService {\n        return \u0026DefaultUserService{logger: log}\n    })\n\n    // Resolve and use\n    service := di.MustResolve[UserService](container)\n    user := service.GetUser(42)\n    fmt.Println(\"Got:\", user)\n}\n```\n\n## API Reference\n\n### Creating a Container\n\n```go\ncontainer := di.New()\n```\n\n### Registering Dependencies\n\n#### Basic Registration with Factory\n\n```go\n// Factory with no dependencies\ndi.Register[Logger](container, func() Logger {\n    return \u0026ConsoleLogger{}\n})\n\n// Factory with dependencies (auto-resolved)\ndi.Register[UserService](container, func(logger Logger, db Database) UserService {\n    return \u0026DefaultUserService{logger: logger, db: db}\n})\n\n// Factory that can return an error\ndi.Register[Database](container, func(config Config) (Database, error) {\n    return NewPostgresDB(config.DatabaseURL())\n})\n```\n\n#### Register an Existing Instance\n\n```go\nconfig := \u0026AppConfig{Port: 8080}\ndi.RegisterInstance[Config](container, config)\n```\n\n#### Register Interface → Implementation Mapping\n\n```go\ndi.RegisterType[UserRepository, PostgresUserRepository](container, di.AsSingleton())\n```\n\n### Lifetime Options\n\n| Lifetime | Behavior |\n|----------|----------|\n| `Transient` | New instance created on every resolution (default) |\n| `Singleton` | Single instance shared across all resolutions |\n| `Scoped` | Single instance per scope (e.g., per HTTP request) |\n\n```go\n// Transient (default)\ndi.Register[Service](c, factory)\ndi.Register[Service](c, factory, di.AsTransient())\n\n// Singleton\ndi.Register[Service](c, factory, di.AsSingleton())\n\n// Scoped\ndi.Register[Service](c, factory, di.AsScoped())\n\n// Using WithLifetime\ndi.Register[Service](c, factory, di.WithLifetime(di.Singleton))\n```\n\n### Resolving Dependencies\n\n```go\n// Returns (T, error)\nservice, err := di.Resolve[UserService](container)\nif err != nil {\n    log.Fatal(err)\n}\n\n// Panics on error (use when you know registration exists)\nservice := di.MustResolve[UserService](container)\n```\n\n### Named Registrations\n\nRegister multiple implementations of the same interface:\n\n```go\n// Register with names\ndi.Register[Logger](c, func() Logger {\n    return \u0026ConsoleLogger{}\n}, di.WithName(\"console\"))\n\ndi.Register[Logger](c, func() Logger {\n    return \u0026FileLogger{path: \"/var/log/app.log\"}\n}, di.WithName(\"file\"))\n\n// Resolve by name\nconsoleLogger, _ := di.ResolveNamed[Logger](c, \"console\")\nfileLogger, _ := di.ResolveNamed[Logger](c, \"file\")\n```\n\n### Scoped Resolution\n\nScopes are useful for request-scoped dependencies in web applications:\n\n```go\ndi.Register[*RequestContext](c, func() *RequestContext {\n    return \u0026RequestContext{\n        RequestID: uuid.New().String(),\n        StartTime: time.Now(),\n    }\n}, di.AsScoped())\n\n// Per HTTP request\nfunc handler(w http.ResponseWriter, r *http.Request) {\n    scope := container.CreateScope(\"request-\" + r.Header.Get(\"X-Request-ID\"))\n\n    // Same instance within this scope\n    ctx1, _ := di.ResolveInScope[*RequestContext](container, scope)\n    ctx2, _ := di.ResolveInScope[*RequestContext](container, scope)\n    // ctx1 == ctx2 ✓\n}\n```\n\n### Utility Methods\n\n```go\n// Check if a type is registered\nif di.Has[Logger](container) {\n    // ...\n}\n\n// Check named registration\nif di.HasNamed[Logger](container, \"file\") {\n    // ...\n}\n\n// Clear all registrations\ncontainer.Clear()\n```\n\n## Error Handling\n\nThe library provides typed errors for precise error handling:\n\n```go\nservice, err := di.Resolve[UserService](container)\nif err != nil {\n    switch e := err.(type) {\n    case di.ErrNotRegistered:\n        log.Printf(\"Type %s is not registered\", e.Type)\n    case di.ErrCircularDependency:\n        log.Printf(\"Circular dependency: %v\", e.Chain)\n    case di.ErrResolutionFailed:\n        log.Printf(\"Failed to resolve %s: %v\", e.Type, e.Cause)\n    case di.ErrInvalidFactory:\n        log.Printf(\"Invalid factory for %s: %s\", e.Type, e.Message)\n    }\n}\n```\n\n| Error Type | When It Occurs |\n|------------|----------------|\n| `ErrNotRegistered` | Attempting to resolve an unregistered type |\n| `ErrCircularDependency` | A → B → A dependency chain detected |\n| `ErrResolutionFailed` | Factory returned an error or dependency failed |\n| `ErrInvalidFactory` | Factory signature is invalid |\n| `ErrScopeNotFound` | Referenced scope doesn't exist |\n\n## Complete Example\n\nHere's a realistic example with a layered architecture:\n\n```go\npackage main\n\nimport (\n    \"database/sql\"\n    \"log\"\n    \"net/http\"\n\n    \"github.com/pegasusheavy/go-dependency-injector/di\"\n)\n\n// Interfaces\ntype Config interface {\n    DatabaseURL() string\n    Port() string\n}\n\ntype Logger interface {\n    Info(msg string)\n    Error(msg string)\n}\n\ntype UserRepository interface {\n    FindByID(id int) (*User, error)\n}\n\ntype UserService interface {\n    GetUser(id int) (*User, error)\n}\n\ntype UserHandler interface {\n    ServeHTTP(w http.ResponseWriter, r *http.Request)\n}\n\n// Bootstrap the application\nfunc main() {\n    container := di.New()\n\n    // Infrastructure layer\n    di.Register[Config](container, NewEnvConfig, di.AsSingleton())\n    di.Register[Logger](container, NewZapLogger, di.AsSingleton())\n    di.Register[*sql.DB](container, func(cfg Config) (*sql.DB, error) {\n        return sql.Open(\"postgres\", cfg.DatabaseURL())\n    }, di.AsSingleton())\n\n    // Data layer\n    di.Register[UserRepository](container, NewPostgresUserRepo)\n\n    // Business layer\n    di.Register[UserService](container, NewUserService)\n\n    // Presentation layer\n    di.Register[UserHandler](container, NewUserHandler)\n\n    // Start server\n    handler := di.MustResolve[UserHandler](container)\n    config := di.MustResolve[Config](container)\n\n    log.Printf(\"Starting server on %s\", config.Port())\n    http.ListenAndServe(config.Port(), handler)\n}\n```\n\n## Best Practices\n\n### 1. Register at Startup\n\nRegister all dependencies during application startup, not at runtime:\n\n```go\nfunc main() {\n    container := di.New()\n    registerDependencies(container)  // All registrations here\n    runApplication(container)\n}\n```\n\n### 2. Depend on Interfaces\n\nAlways register and resolve interfaces, not concrete types:\n\n```go\n// ✓ Good\ndi.Register[Logger](c, func() Logger { return \u0026ConsoleLogger{} })\n\n// ✗ Avoid\ndi.Register[*ConsoleLogger](c, func() *ConsoleLogger { return \u0026ConsoleLogger{} })\n```\n\n### 3. Use Appropriate Lifetimes\n\n- **Singleton**: Stateless services, configuration, connection pools\n- **Transient**: Stateful objects, request-specific data\n- **Scoped**: Per-request context, unit of work patterns\n\n### 4. Keep Factories Simple\n\nFactories should only create objects, not perform business logic:\n\n```go\n// ✓ Good\ndi.Register[UserService](c, func(repo UserRepository, log Logger) UserService {\n    return \u0026DefaultUserService{repo: repo, logger: log}\n})\n\n// ✗ Avoid\ndi.Register[UserService](c, func(repo UserRepository) UserService {\n    users, _ := repo.FindAll()  // Don't do this!\n    return \u0026UserService{cachedUsers: users}\n})\n```\n\n## Testing\n\nThe DI container makes testing easy by allowing you to swap implementations:\n\n```go\nfunc TestUserService(t *testing.T) {\n    container := di.New()\n\n    // Register mock dependencies\n    di.RegisterInstance[Logger](container, \u0026MockLogger{})\n    di.RegisterInstance[UserRepository](container, \u0026MockUserRepo{\n        users: map[int]*User{1: {ID: 1, Name: \"Test\"}},\n    })\n\n    // Register the real service\n    di.Register[UserService](container, NewUserService)\n\n    // Test\n    service := di.MustResolve[UserService](container)\n    user, err := service.GetUser(1)\n\n    assert.NoError(t, err)\n    assert.Equal(t, \"Test\", user.Name)\n}\n```\n\n## Thread Safety\n\nThe container is fully thread-safe. You can safely:\n\n- Register dependencies from multiple goroutines\n- Resolve dependencies concurrently\n- Create scopes in parallel\n\n## Requirements\n\n- Go 1.22 or later (uses generics)\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Package Discovery\n\nThis package is automatically indexed by [pkg.go.dev](https://pkg.go.dev/github.com/pegasusheavy/go-dependency-injector) once you create a version tag. Users can:\n\n- Browse documentation at https://pkg.go.dev/github.com/pegasusheavy/go-dependency-injector\n- Import directly: `go get github.com/pegasusheavy/go-dependency-injector`\n- View examples and API documentation\n\n### For Maintainers\n\nTo publish a new version:\n\n```bash\n# Create and push a new semantic version tag\ngit tag v1.0.0\ngit push origin v1.0.0\n\n# The package will be automatically indexed by pkg.go.dev\n# You can verify at: https://pkg.go.dev/github.com/pegasusheavy/go-dependency-injector@v1.0.0\n```\n\n## Related Projects\n\n- [uber-go/dig](https://github.com/uber-go/dig) - Reflection-based DI framework\n- [google/wire](https://github.com/google/wire) - Compile-time DI code generator\n- [samber/do](https://github.com/samber/do) - Generic-based DI container\n\n## Search Terms\n\nIf you're looking for any of these, you've found the right package:\n\n- **Dependency Injection in Go** / **Golang DI** - This package provides full DI support\n- **IoC Container for Go** / **Inversion of Control** - Implements the IoC pattern\n- **Service Container** / **Service Locator** - Acts as a service container for your application\n- **Constructor Injection** - Automatically injects dependencies via constructor functions\n- **Lifetime Management** - Supports Transient, Singleton, and Scoped lifetimes\n- **Interface-based DI** - Designed for programming to interfaces\n\n## FAQ\n\n### Why use this over uber-go/dig or google/wire?\n\n- **Type Safety**: Uses generics for compile-time type checking\n- **Simplicity**: Minimal API surface with intuitive methods\n- **Zero Dependencies**: No external dependencies\n- **Modern Go**: Built for Go 1.22+ with generics\n\n### Can I use this in production?\n\nYes! The library is fully tested, thread-safe, and follows Go best practices.\n\n### How does performance compare?\n\nSee `di/benchmark_test.go` for benchmarks. Performance is comparable to other DI solutions with minimal overhead.\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\nPlease feel free to submit a Pull Request or open an issue for bugs, features, or questions.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquinnjr%2Fgo-dependency-injector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquinnjr%2Fgo-dependency-injector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquinnjr%2Fgo-dependency-injector/lists"}