55[ ![ Coverage Status] ( https://coveralls.io/repos/github/golobby/container/badge.svg?branch=master )] ( https://coveralls.io/github/golobby/container?branch=master )
66
77# Container
8- A lightweight yet powerful IoC dependency injection container for Go projects.
9- It provides an easy-to-use interface and performance-in-mind dependency injection container to be your ultimate requirement.
8+ GoLobby Container is a lightweight yet powerful IoC dependency injection container for Go projects.
9+ It is an easy-to-use and performance-in-mind dependency injection container to be your ultimate requirement.
1010
1111## Documentation
1212
1313### Required Go Versions
1414It requires Go ` v1.11 ` or newer versions.
1515
1616### Installation
17- To install this package, run the following command in the root of your project.
17+ To install this package, run the following command in your project directory .
1818
1919``` bash
20- go get github.com/golobby/container/v2
20+ go get github.com/golobby/container/v3
2121```
2222
2323### Introduction
24- This package is an IoC (dependency injection) container. It can bind abstractions to implementations.
25- Binding is the process of introducing appropriate concretes (implementations) to an IoC container.
24+ GoLobby Container is used to bind abstractions to their implementations.
25+ Binding is the process of introducing appropriate concretes (implementations) of abstractions to an IoC container.
2626In this process, you also determine the resolving type, singleton or transient.
27- In singleton bindings, the container provides an instance once and reuses in the rest of the injections.
28- In transient bindings, the container always returns a brand new instance for each injection.
29- After the binding process, you can ask the IoC container for the appropriate implementation of the abstraction.
30- Then your code will depend on abstractions, not implementations.
27+ In singleton bindings, the container provides an instance once and returns it for all the requests.
28+ In transient bindings, the container always returns a brand-new instance for each request.
29+ After the binding process, you can ask the IoC container to make the appropriate implementation of the abstraction that your code needs.
30+ Then your code will depend on abstractions, not implementations!
31+
3132
3233### Quick Start
3334
3435The following example demonstrates a simple binding and resolving.
3536
3637``` go
37- // Bind Config (interface) to JsonConfig
38+ // Bind Config (interface) to JsonConfig (struct)
3839err := container.Singleton (func () Config {
3940 return &JsonConfig{...}
4041})
4142
4243var c Config
4344err := container.Bind (&c)
44- // `c` will be an instance of JsonConfig
45+ // `c` will be the instance of JsonConfig
4546```
4647
47- ### Binding
48+ ### Typed Binding
4849
4950#### Singleton
5051
@@ -56,7 +57,7 @@ err := container.Singleton(func() Abstraction {
5657})
5758```
5859
59- It takes a resolver function whose return type is the abstraction and the function body returns the concrete (implementation).
60+ It takes a function (resolver) whose return type is the abstraction and the function body returns the concrete (implementation).
6061
6162Example for singleton binding:
6263
@@ -66,7 +67,7 @@ err := container.Singleton(func() Database {
6667})
6768```
6869
69- In the example above, the container makes a MySQL instance once and returns it for all requests.
70+ In the example above, the container makes a MySQL instance once and returns it for all the requests.
7071
7172#### Transient
7273
@@ -80,34 +81,70 @@ err := container.Transient(func() Shape {
8081})
8182```
8283
83- In the example above, the container always returns a brand new Rectangle instance for each request.
84+ In the example above, the container always returns a brand-new Rectangle instance for each request.
85+
86+ ### Named Bindings
87+
88+ You may have different concretes for an abstraction.
89+ In this case, you can use named bindings instead of typed bindings.
90+ Named bindings take a name into account as well.
91+ The rest is similar to typed bindings.
92+ The following examples demonstrate named bindings.
93+
94+ ``` go
95+ // Singleton
96+ err := container.NamedSingleton (" square" func () Shape {
97+ return &Rectangle{}
98+ })
99+ err := container.NamedSingleton (" rounded" func () Shape {
100+ return &Circle{}
101+ })
102+
103+ // Transient
104+ err := container.NamedTransient (" sql" func () Database {
105+ return &MySQL{}
106+ })
107+
108+ err := container.NamedTransient (" noSql" func () Database {
109+ return &MongoDB{}
110+ })
111+ ```
84112
85113### Resolving
86114
87- Container resolves the dependencies with the ` Bind ()` , ` Call() ` , and ` Fill() ` methods.
115+ Container resolves the dependencies with the ` Resolve ()` , ` Call() ` , and ` Fill() ` methods.
88116
89117#### Using References
90118
91- The ` Bind ()` method takes a reference of the abstraction type and binds it to the appropriate concrete from the container .
119+ The ` Resolve ()` method takes reference of the abstraction type and fills it with the appropriate concrete.
92120
93121``` go
94122var a Abstraction
95- err := container.Bind (&a)
123+ err := container.Resolve (&a)
96124// `a` will be an implementation of the Abstraction
97125```
98126
99- Example of resolving using refrences :
127+ Example of resolving using references :
100128
101129``` go
102130var m Mailer
103- err := container.Bind (&m)
131+ err := container.Resolve (&m)
104132// `m` will be an implementation of the Mailer interface
105133m.Send (" contact@miladrahimi.com" , " Hello Milad!" )
106134```
107135
136+ Example of named resolving using references:
137+
138+ ``` go
139+ var s Shape
140+ err := container.NamedResolve (&s, " rounded" )
141+ // `s` will be an implementation of the Shape that named rounded
142+ ```
143+
108144#### Using Closures
109145
110- The ` Call() ` method takes a function (receiver) with arguments of abstractions you need and invokes it with parameters of appropriate concretes from the container.
146+ The ` Call() ` method takes a function (receiver) with arguments of abstractions you need.
147+ It will invoke it with parameters of appropriate concretes.
111148
112149``` go
113150err := container.Call (func (a Abstraction ) {
@@ -124,7 +161,7 @@ err := container.Call(func(db Database) {
124161})
125162```
126163
127- You can also resolve multiple abstractions like tho follwing example:
164+ You can also resolve multiple abstractions like the following example:
128165
129166``` go
130167err := container.Call (func (db Database , s Shape ) {
@@ -133,6 +170,8 @@ err := container.Call(func(db Database, s Shape) {
133170})
134171```
135172
173+ Since Go reflection doesn't let us know function parameter names, the ` Call() ` method cannot resolve named concretes.
174+
136175#### Using Structs
137176
138177The ` Fill() ` method takes a struct (pointer) with fields of abstractions you need and fills the fields.
@@ -141,19 +180,27 @@ Example of resolving using Structs:
141180
142181``` go
143182type App struct {
144- m Mailer ` container:"inject"`
145- d Database ` container:"inject"`
183+ mailer Mailer ` container:"type"`
184+ sql Database ` container:"name"`
185+ noSql Database ` container:"name"`
146186 x int
147187}
148188
149189myApp := App {}
150190
151191err := container.Fill (&myApp)
152- // `myApp.m` will be an implementation of the Mailer interface
153- // `myApp.s` will be an implementation of the Database interface
154- // `myApp.x` will be ignored since it has no `container:"inject"` tag
192+ // [Typed Bindings]
193+ // `myApp.mailer` will be an implementation of the Mailer interface
194+
195+ // [Named Bindings]
196+ // `myApp.sql` will be a sql implementation of the Database interface
197+ // `myApp.noSql` will be a noSql implementation of the Database interface
198+
199+ // `myApp.x` will be ignored since it has no `container` tag
155200```
156201
202+ As for named bindings (struct fields with ` container: "name" ` tag), field names must be the same binding name.
203+
157204#### Binding time
158205
159206You can resolve dependencies at the binding time if you need previous bindings for the new one.
@@ -176,14 +223,15 @@ err := container.Singleton(func(c Config) Database {
176223})
177224```
178225
179- ### Standalone instance
226+ ### Standalone Instance
180227
181- In default, the Container keeps your bindings in the global instance.
228+ By default, the Container keeps your bindings in the global instance.
182229Sometimes you may want to create a standalone instance for a part of your application.
183230If so, create a standalone instance like this example:
184231
185232``` go
186- c := container.New () // returns a container.Container
233+ // returns a container.Container (a Container instance)
234+ c := container.New ()
187235
188236err := c.Singleton (func () Database {
189237 return &MySQL{}
0 commit comments