Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sithira/go_autowired
A Simple yet powerful Dependency container for Go
https://github.com/sithira/go_autowired
dependency-injection golang golang-library golang-pacakge
Last synced: 23 days ago
JSON representation
A Simple yet powerful Dependency container for Go
- Host: GitHub
- URL: https://github.com/sithira/go_autowired
- Owner: Sithira
- License: mit
- Created: 2024-10-21T16:37:36.000Z (28 days ago)
- Default Branch: master
- Last Pushed: 2024-10-21T17:52:46.000Z (28 days ago)
- Last Synced: 2024-10-22T07:52:16.192Z (27 days ago)
- Topics: dependency-injection, golang, golang-library, golang-pacakge
- Language: Go
- Homepage: https://github.com/Sithira/go_autowired
- Size: 148 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: Readme.md
- License: LICENSE
Awesome Lists containing this project
README
# @AutoWired for Go 🚀
`autowired` is a powerful and flexible dependency injection container for Go applications. It provides a robust set of
features for managing dependencies, including lifecycle management, scoping, and automatic wiring of structs. This
package is designed to simplify dependency management in complex Go applications while maintaining type safety and
allowing for flexible configuration.## Features
- Dependency registration with custom names and scopes
- Support for Singleton, Prototype, and Request scopes
- Lifecycle hooks (OnInit, OnStart, OnDestroy)
- Automatic dependency resolution with circular dependency detection
- Type-safe wrappers for common operations
- Struct field auto-wiring
- Thread-safe operations
- Lazy dependency resolution## Installation
To use `autowired` in your Go project, you can install it using:
```bash
go get github.com/Sithira/go_autowired
```## Usage
### Creating a Container
```go
container := autowired.NewContainer()
```### Registering Dependencies
You can register dependencies with different scopes:
```go
// Singleton (default)
err := autowired.Register[MyService](container, func () *MyService {
return &MyService{}
})// Prototype
err := autowired.Register[MyPrototypeService](container, func () *MyPrototypeService {
return &MyPrototypeService{}
}, autowired.Prototype)// Request
err := autowired.Register[MyRequestService](container, func () *MyRequestService {
return &MyRequestService{}
}, autowired.Request)
```### Resolving Dependencies
```go
service, err := autowired.Resolve[*MyService](container)
if err != nil {
// Handle error
}
```### Auto-wiring Structs
```go
type MyApp struct {
Service *MyService `autowire:""`
}app := &MyApp{}
err := autowired.AutoWire(container, app)
if err != nil {
// Handle error
}
```### Using Scoped Dependencies
#### Singleton Scope (Default)
Singleton-scoped dependencies are created once and reused for all resolutions:
```go
type Counter struct {
count int
}func (c *Counter) Increment() {
c.count++
}err := autowired.Register[Counter](container, func () *Counter {
return &Counter{}
})counter1, _ := autowired.Resolve[*Counter](container)
counter1.Increment()counter2, _ := autowired.Resolve[*Counter](container)
counter2.Increment()fmt.Println(counter1.count) // Output: 2
fmt.Println(counter2.count) // Output: 2 (same instance)
```#### Prototype Scope
Prototype-scoped dependencies are created anew for each resolution:
```go
err := autowired.Register[Counter](container, func () *Counter {
return &Counter{}
}, autowired.Prototype)counter1, _ := autowired.Resolve[*Counter](container)
counter1.Increment()counter2, _ := autowired.Resolve[*Counter](container)
counter2.Increment()fmt.Println(counter1.count) // Output: 1
fmt.Println(counter2.count) // Output: 1 (different instance)
```#### Request Scope
Request-scoped dependencies are created once per goroutine (typically per HTTP request):
```go
err := autowired.Register[RequestContext](container, func () *RequestContext {
return &RequestContext{}
}, autowired.Request)http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
ctx, _ := autowired.Resolve[*RequestContext](container)
// Use ctx...defer container.ClearRequestScoped()
})
```### Lifecycle Hooks
You can define lifecycle hooks for your dependencies:
```go
hooks := autowired.LifecycleHooks[*MyService]{
OnInit: func (s *MyService) error {
fmt.Println("Initializing MyService")
return nil
},
OnStart: func (s *MyService) error {
fmt.Println("Starting MyService")
return nil
},
OnDestroy: func (s *MyService) error {
fmt.Println("Destroying MyService")
return nil
},
}err := autowired.Register[MyService](container, func () *MyService {
return &MyService{}
}, hooks)
```### Handling Circular Dependencies
The container automatically detects circular dependencies:
```go
err := autowired.Register[ServiceA](container, func (b *ServiceB) *ServiceA {
return &ServiceA{B: b}
})err := autowired.Register[ServiceB](container, func (a *ServiceA) *ServiceB {
return &ServiceB{A: a}
})// This will return an error due to circular dependency
_, err := autowired.Resolve[*ServiceA](container)
if err != nil {
fmt.Println("Circular dependency detected:", err)
}
```### Custom Naming
You can register dependencies with custom names:
```go
err := autowired.Register[MyService](container, func () *MyService {
return &MyService{}
}, "customName")service, err := autowired.Resolve[*MyService](container, "customName")
```### Container Cleanup
Don't forget to clean up the container when you're done:
```go
err := container.Destroy()
if err != nil {
// Handle error
}
```## Best Practices
1. Use Singleton scope for stateless services or when you want to share state across the application.
2. Use Prototype scope when you need a fresh instance each time or for stateful services that shouldn't share state.
3. Use Request scope in web applications for request-specific data.
4. Always handle errors returned by Register, Resolve, and AutoWire.
5. Use lifecycle hooks for proper resource management.
6. Avoid circular dependencies in your application design.## Thread Safety
The `autowired` package is designed to be thread-safe, allowing for concurrent use in multithreaded applications.
However, be mindful of the thread safety of the dependencies you're managing within the container.## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Support
If you find this plugin useful, show your support by:
- Giving it a ⭐️ on [GitHub](https://github.com/Sithira/go_autowired)
- Leaving a like on Pub
- Showing some ♥️ and buying me a coffee via USDT-TR20 at this address: `TNuTkL1ZJGu2xntmtzHzSiH5YdVqUeAujr`**Enjoy the plugin!**
Sithira ✌️