Documentation
¶
Overview ¶
Package inject provides dependency injection for Go. For small Go applications, manually constructing all required objects is more than sufficient. But for large, modular code bases, dependency injection can alleviate a lot of boilerplate.
The following example illustrates a simple modular application.
First, the main package installs configured modules and calls an entry point:
package main func run(db *mgo.Database, log *log.Logger) { log.Println("starting application") // ... } func main() { injector := New() injector.Install( &MongoModule{URI: "mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000"""}, &LoggingModule{Flags: log.Ldate | log.Ltime | log.Llongfile}, ) injector.Call(run) }
Next we have a simple Mongo module with a configurable URI:
package db type MongoModule struct { URI string } func (m *MongoModule) ProvideMongoDB() (*mgo.Database, error) { return mgo.Dial(m.URI) }
The logging package shows idiomatic use of inject; it is just a thin wrapper around normal Go constructors. This is the least invasive way of using injection, and preferred.
package logging // LoggingModule provides a *log.Logger that writes log lines to a Mongo collection. type LoggingModule struct { Flags int } func (l *LoggingModule) ProvideMongoLogger(db *mgo.Database) *log.Logger { return NewMongoLogger(db, l.Flags) } type logEntry struct { Text string `bson:"text"` } func NewMongoLogger(db *mgo.Database, flags int) *log.Logger { return log.New(&mongologWriter{c: db.C("logs")}, "", flags) } type mongoLogWriter struct { buf string c *mgo.Collection } func (m *mongoLogWriter) Write(b []byte) (int, error) { m.buf = m.buf + string(b) for { eol := strings.Index(m.buf, "\n") if eol == -1 { return len(b), nil } line := m.buf[:eol] err := m.c.Insert(&logEntry{line}) if err != nil { return len(b), err } m.buf = m.buf[eol:] } }
Two interfaces to the injector are provided: SafeInjector and Injector. The former will return error values and the latter will panic on any error. The latter is commonly used because DI failures are typically not user-recoverable.
See the [README](https://github.com/alecthomas/inject/blob/master/README.md) for more details.
Index ¶
- type Annotation
- type Binder
- type Binding
- type Injector
- func (i *Injector) Bind(things ...interface{}) Binder
- func (i *Injector) BindTo(iface interface{}, impl interface{}) Binder
- func (i *Injector) Call(f interface{}) []interface{}
- func (i *Injector) Child() *Injector
- func (i *Injector) Get(t reflect.Type) interface{}
- func (i *Injector) Install(modules ...interface{}) Binder
- func (i *Injector) Safe() *SafeInjector
- func (i *Injector) Validate(f interface{}) error
- type Module
- type SafeBinder
- type SafeInjector
- func (s *SafeInjector) Bind(things ...interface{}) error
- func (s *SafeInjector) BindTo(as interface{}, impl interface{}) error
- func (s *SafeInjector) Call(f interface{}) ([]interface{}, error)
- func (s *SafeInjector) Child() *SafeInjector
- func (s *SafeInjector) Get(t interface{}) (interface{}, error)
- func (s *SafeInjector) Install(modules ...interface{}) (err error)
- func (s *SafeInjector) Unsafe() *Injector
- func (s *SafeInjector) Validate(f interface{}) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Annotation ¶
type Annotation interface { // Build returns the type associated with the value being bound, and a function that builds that // value at runtime. Build(*SafeInjector) (*Binding, error) // Is checks if the annotation or any children are of the given annotation type. Is(annotation Annotation) bool }
An Annotation modifies how a type is built and retrieved from the SafeInjector.
func Annotate ¶
func Annotate(v interface{}) Annotation
Annotate ensures that v is an annotation, and returns it.
Specifically:
- If v is already an Annotation it will be returned as-is. - If v is a function it will be converted to a Provider(). - Any other value will become a Literal().
func Literal ¶
func Literal(v interface{}) Annotation
Literal annotates a value as being provided as-is with no further transformation.
func Mapping ¶
func Mapping(v interface{}) Annotation
Mapping annotates a provider or binding to indicate it is part of a mapping of keys to values.
injector.Bind(Mapping(map[string]int{"one": 1})) injector.Bind(Mapping(map[string]int{"two": 2})) injector.Provide(Mapping(func() map[string]int { return map[string]int{"three": 3} })) expected := map[string]int{"one": 1, "two": 2, "three": 3} actual := injector.Get(reflect.TypeOf(map[string]int{})) assert.Equal(t, actual, expected)
func Provider ¶
func Provider(v interface{}) Annotation
Provider annotates a function to indicate it should be called whenever the type of its return value is requested.
func Sequence ¶
func Sequence(v interface{}) Annotation
Sequence annotates a provider or binding to indicate it is part of a slice of values implementing the given type.
injector.Bind(Sequence([]int{1})) injector.Bind(Sequence([]int{2})) expected := []int{1, 2} actual := injector.Get(reflect.TypeOf([]int{})) assert.Equal(t, actual, expected)
func Singleton ¶
func Singleton(v interface{}) Annotation
Singleton annotates a provider function to indicate that the provider will only be called once, and that its return value will be used for all subsequent retrievals of the given type.
count := 0 injector.Bind(Singleton(func() int { count++ return 123 })) injector.Get(reflect.TypeOf(1)) injector.Get(reflect.TypeOf(1)) assert.Equal(t, 1, count)
type Binder ¶
type Binder interface { Bind(things ...interface{}) Binder BindTo(to interface{}, impl interface{}) Binder Install(module ...interface{}) Binder }
Binder is an interface allowing bindings to be added.
type Binding ¶
type Binding struct { Provides reflect.Type Requires []reflect.Type Build func() (interface{}, error) }
Binding represents a function that resolves to a value given a set of input values.
type Injector ¶
type Injector struct {
// contains filtered or unexported fields
}
SafeInjector is an IoC container.
func New ¶
func New() *Injector
New creates a new Injector.
An unsafe injector panics on any error. This is commonly used because DI failures are generally not user-recoverable.
The injector itself is already bound, as is an implementation of the Binder interface.
func (*Injector) Bind ¶
Bind binds a value to the injector. Panics on error. See the README (https://github.com/alecthomas/inject/blob/master/README.md) for more details.
func (*Injector) BindTo ¶
BindTo binds an interface to a value. Panics on error.
"as" should either be a nil pointer to the required interface:
i.BindTo((*fmt.Stringer)(nil), impl)
Or a type to convert to:
i.BindTo(int64(0), 10)
func (*Injector) Call ¶
func (i *Injector) Call(f interface{}) []interface{}
Call calls f, injecting any arguments, and panics if the function errors.
func (*Injector) Child ¶
Child creates a child Injector whose bindings overlay those of the parent.
The parent will never be modified by the child.
func (*Injector) Get ¶
Get acquires a value of type t from the injector.
It is usually preferable to use Call().
func (*Injector) Install ¶
Install a module. A module is a struct whose methods are providers. This is useful for grouping configuration data together with providers.
Duplicate modules are allowed as long as all fields are identical or either the existing module, or the new module, are zero value.
Any method starting with "Provide" will be bound as a Provider. If the method name contains "Multi" it will not be a singleton provider. If the method name contains "Sequence" it must return a slice which is merged with slices of the same type. If the method name contains "Mapping" it must return a mapping which will be merged with mappings of the same type. Mapping and Sequence can not be used simultaneously.
Arguments to provider methods are injected.
For example, the following method will be called only once:
ProvideLog() *log.Logger { return log.New(...) }
While this method will be called each time a *log.Logger is injected.
ProvideMultiLog() *log.Logger { return log.New(...) }
func (*Injector) Safe ¶
func (i *Injector) Safe() *SafeInjector
Safe returns the underlying SafeInjector.
type Module ¶
A Module implementing this interface will have its Configure() method called at Install() time.
type SafeBinder ¶
type SafeInjector ¶
type SafeInjector struct {
// contains filtered or unexported fields
}
SafeInjector is an IoC container.
func SafeNew ¶
func SafeNew() *SafeInjector
SafeNew creates a new SafeInjector.
The injector itself is already bound, as is an implementation of the Binder interface.
func (*SafeInjector) Bind ¶
func (s *SafeInjector) Bind(things ...interface{}) error
Bind binds a value to the injector. See Injector.Bind() for details.
func (*SafeInjector) BindTo ¶
func (s *SafeInjector) BindTo(as interface{}, impl interface{}) error
BindTo binds an implementation to an interface. See Injector.BindTo() for details.
func (*SafeInjector) Call ¶
func (s *SafeInjector) Call(f interface{}) ([]interface{}, error)
Call f, injecting any arguments.
func (*SafeInjector) Child ¶
func (s *SafeInjector) Child() *SafeInjector
Child creates a child SafeInjector whose bindings overlay those of the parent.
The parent will never be modified by the child.
func (*SafeInjector) Get ¶
func (s *SafeInjector) Get(t interface{}) (interface{}, error)
Get acquires a value of type t from the injector.
It is usually preferable to use Call().
func (*SafeInjector) Install ¶
func (s *SafeInjector) Install(modules ...interface{}) (err error)
Install installs a module. See Injector.Install() for details.
func (*SafeInjector) Unsafe ¶
func (s *SafeInjector) Unsafe() *Injector
func (*SafeInjector) Validate ¶
func (s *SafeInjector) Validate(f interface{}) error
Validate that the function f can be called by the injector.