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" ) func main() { // build container container, err := inject.New( // inject constructor inject.Provide(NewLogger), inject.Provide(NewServer), // inject as interface inject.Provide(NewRouter, inject.As(new(http.Handler)), // *http.Server mux implements http.Handler interface ), // controller interface group inject.Provide(&AccountController{}, inject.As(new(Controller)), // add AccountController to controller group inject.WithName("account"), inject.Exported(), // inject all exported fields ), inject.Provide(&AuthController{}, inject.As(new(Controller)), // add AuthController to controller group inject.WithName("auth"), inject.Exported(), // inject all exported fields ), ) // build error if err != nil { panic(err) } // 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 } // RegisterRoutes func (c *AccountController) RegisterRoutes(mux *http.ServeMux) { c.Logger.Println("AccountController registered!") // register your routes } // AuthController type AuthController struct { Logger *log.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 ¶
var (
ErrTypeNotProvided = graph.ErrTypeNotProvided
)
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.Provider.
type AdminServerProvider struct { inject.Provider AdminMux http.Handler `inject:"admin"` // use named definition } func (p *AdminServerProvider) Provide() *http.Server { return &http.Server{ Handler: p.AdminMux, } }
func Replace ¶
func Replace(provider interface{}, options ...ProvideOption) Option
Replace replaces a already provided definition to another one. This method also works like Provide(). The difference is that Replace() replaces already provided definition. The method returns an error when the container does not provide a replaceable definition.
You may replace concrete provided type to another one.
inject.New( inject.Provide(&http.Server{Addr: ":80"}), inject.Replace(&http.Server{Addr: ":8080"}), )
Alternatively, it may replace one interface implementation to another one.
inject.New( inject.Provide(&http.ServeMux{}, inject.As(new(http.Handler))), inject.Replace(&mux.AnotherMux{}, inject.As(new(http.Handler))), )
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 implements 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 Exported ¶
func Exported() ProvideOption
Exported indicates that all public fields of the structure should be injected.
type AccountController struct { Accounts AccountRepository // will be injected without tag 'inject' } inject.Provide(NewAccountRepository, inject.As(new(AccountRepository))) inject.Provide(&AccountController{}, inject.Exported())
Also works with inject.Provider structures.
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"))
type Provider ¶ added in v1.2.0
type Provider struct { }
Provider helper struct that indicates that structure is injection provider.
func (*Provider) IsInjectProvider ¶ added in v1.2.0
func (p *Provider) IsInjectProvider()
IsInjectProvider ...