Documentation
¶
Overview ¶
Package inject make your dependency injection easy. Container allows you to inject dependencies into constructors or structures without the need to have specified each argument manually.
Provide ¶
First of all, when creating a new container, you need to describe how to create each instance of a dependency. To do this, use the container option inject.Provide().
container, err := New(
Provide(NewDependency),
Provide(NewAnotherDependency)
)
func NewDependency(dependency *pkg.AnotherDependency) *pkg.Dependency {
return &pkg.Dependency{
dependency: dependency,
}
}
func NewAnotherDependency() (*pkg.AnotherDependency, error) {
if dependency, err = initAnotherDependency(); err != nil {
return nil, err
}
return dependency, nil
}
Now, container knows how to create *pkg.Dependency and *pkg.AnotherDependency. For advanced providing see inject.Provide() and inject.ProvideOption documentation.
Extract ¶
After building a container, it is easy to get any previously provided type. To do this, use the container's Extract() method.
var anotherDependency *pkg.AnotherDependency
if err = container.Extract(&anotherDependency); err != nil {
// handle error
}
The container collects a dependencies of *pkg.AnotherDependency, creates its instance and places it in a target pointer. For advanced extraction see Extract() and inject.ExtractOption documentation.
Example ¶
package main
import (
"log"
"net/http"
"os"
"github.com/defval/inject/v2"
)
func main() {
// build container
container := inject.New(
// inject constructor
inject.Provide(NewLogger),
inject.Provide(NewServer),
// inject as interface
inject.Provide(NewRouter,
inject.As(new(http.Handler)), // *http.Server mux interfaces http.Handler interface
),
// controller interface group
inject.Provide(NewAccountController,
inject.As(new(Controller)), // add AccountController to controller group
),
inject.Provide(NewAuthController,
inject.As(new(Controller)), // add AuthController to controller group
),
)
// extract server from container
var server *http.Server
if err := container.Extract(&server); err != nil {
panic(err)
}
}
// NewLogger
func NewLogger() *log.Logger {
logger := log.New(os.Stdout, "", 0)
defer logger.Println("Logger loaded")
return logger
}
// NewServer
func NewServer(logger *log.Logger, handler http.Handler) *http.Server {
defer logger.Println("Server created!")
return &http.Server{
Handler: handler,
}
}
// NewRouter
func NewRouter(logger *log.Logger, controllers []Controller) *http.ServeMux {
logger.Println("Create router")
defer logger.Println("Router created!")
mux := &http.ServeMux{}
for _, ctrl := range controllers {
ctrl.RegisterRoutes(mux)
}
return mux
}
// Controller
type Controller interface {
RegisterRoutes(mux *http.ServeMux)
}
// AccountController
type AccountController struct {
Logger *log.Logger
}
func NewAccountController(logger *log.Logger) *AccountController {
return &AccountController{Logger: logger}
}
// RegisterRoutes
func (c *AccountController) RegisterRoutes(mux *http.ServeMux) {
c.Logger.Println("AccountController registered!")
// register your routes
}
// AuthController
type AuthController struct {
Logger *log.Logger
}
func NewAuthController(logger *log.Logger) *AuthController {
return &AuthController{Logger: logger}
}
// RegisterRoutes
func (c *AuthController) RegisterRoutes(mux *http.ServeMux) {
c.Logger.Println("AuthController registered!")
// register your routes
}
Output: Logger loaded Create router AccountController registered! AuthController registered! Router created! Server created!
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Container ¶
type Container struct {
// contains filtered or unexported fields
}
Container is a dependency injection container.
func (*Container) Extract ¶
func (c *Container) Extract(target interface{}, options ...ExtractOption) (err error)
Extract populates given target pointer with type instance provided in the container.
var server *http.Server
if err = container.Extract(&server); err != nil {
// extract failed
}
If the target type does not exist in a container or instance type building failed, Extract() returns an error. Use ExtractOption for modifying the behavior of this function.
type ExtractOption ¶
type ExtractOption interface {
// contains filtered or unexported methods
}
ExtractOption modifies default extract behavior. See inject.Name().
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures container. See inject.Provide(), inject.Bundle(), inject.Replace().
func Bundle ¶
Bundle group together container options.
accountBundle := inject.Bundle( inject.Provide(NewAccountController), inject.Provide(NewAccountRepository), ) authBundle := inject.Bundle( inject.Provide(NewAuthController), inject.Provide(NewAuthRepository), ) container, _ := New( accountBundle, authBundle, )
func Provide ¶
func Provide(provider interface{}, options ...ProvideOption) Option
Provide returns container option that explains how to create an instance of a type inside a container.
The first argument is the provider. The provider can be constructor function, a pointer to a structure (or just structure) or everything else. There are some differences between these providers.
A constructor function is a function that creates an instance of the required type. It can take an unlimited number of arguments needed to create an instance - the first returned value.
func NewServer(mux *http.ServeMux) *http.Server {
return &http.Server{
Handle: mux,
}
}
Optionally, you can return a initializing error.
func NewServer(mux *http.ServeMux) (*http.Server, err error) {
if time.Now().Day = 1 {
return nil, errors.New("the server is down on the first day of a month")
}
return &http.Server{
Handler: mux,
}
}
Other function signatures will cause error.
For advanced providing use inject.dependencyProvider.
type AdminServerProvider struct {
inject.dependencyProvider
AdminMux http.Handler `inject:"admin"` // use named definition
}
func (p *AdminServerProvider) Provide() *http.Server {
return &http.Server{
Handler: p.AdminMux,
}
}
type ProvideOption ¶
type ProvideOption interface {
// contains filtered or unexported methods
}
ProvideOption modifies default provide behavior. See inject.WithName(), inject.As(), inject.Exported().
func As ¶
func As(ifaces ...interface{}) ProvideOption
As specifies interfaces that implement provider instance. Provide with As() automatically checks that instance interfaces interface and creates slice group with it.
Provide(&http.ServerMux{}, inject.As(new(http.Handler)))
var handler http.Handler
container.Extract(&handler) // extract as interface
var handlers []http.Handler
container.Extract(&handlers) // extract group
func WithName ¶
func WithName(name string) ProvideOption
WithName sets string identifier for provided value.
inject.Provide(&http.Server{}, inject.WithName("first"))
inject.Provide(&http.Server{}, inject.WithName("second"))
container.Extract(&server, inject.Name("second"))
