Skip to content

Commit d0f798f

Browse files
authored
v3
v3
1 parent e7dfae9 commit d0f798f

File tree

5 files changed

+231
-203
lines changed

5 files changed

+231
-203
lines changed

README.md

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,47 @@
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
1414
It 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.
2626
In 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

3435
The following example demonstrates a simple binding and resolving.
3536

3637
```go
37-
// Bind Config (interface) to JsonConfig
38+
// Bind Config (interface) to JsonConfig (struct)
3839
err := container.Singleton(func() Config {
3940
return &JsonConfig{...}
4041
})
4142

4243
var c Config
4344
err := 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

6162
Example 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
94122
var 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
102130
var m Mailer
103-
err := container.Bind(&m)
131+
err := container.Resolve(&m)
104132
// `m` will be an implementation of the Mailer interface
105133
m.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
113150
err := 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
130167
err := 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

138177
The `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
143182
type 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

149189
myApp := App{}
150190

151191
err := 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

159206
You 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.
182229
Sometimes you may want to create a standalone instance for a part of your application.
183230
If 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

188236
err := c.Singleton(func() Database {
189237
return &MySQL{}

container.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
package container
44

55
import (
6-
internal "github.com/golobby/container/v2/pkg/container"
6+
internal "github.com/golobby/container/v3/pkg/container"
77
)
88

99
// New creates a new standalone instance of Container
@@ -21,36 +21,42 @@ func Singleton(resolver interface{}) error {
2121
return container.Singleton(resolver)
2222
}
2323

24+
// NamedSingleton binds like the Singleton method but for named bindings.
25+
func NamedSingleton(name string, resolver interface{}) error {
26+
return container.NamedSingleton(name, resolver)
27+
}
28+
2429
// Transient will bind an abstraction to a concrete for further transient resolves.
2530
// It takes a resolver function which returns the concrete and its return type matches the abstraction (interface).
2631
// The resolver function can have arguments of abstraction that have bound already in Container.
2732
func Transient(resolver interface{}) error {
2833
return container.Transient(resolver)
2934
}
3035

36+
// NamedTransient binds like the Transient method but for named bindings.
37+
func NamedTransient(name string, resolver interface{}) error {
38+
return container.NamedTransient(name, resolver)
39+
}
40+
3141
// Reset will reset the container and remove all the existing bindings.
3242
func Reset() {
3343
container.Reset()
3444
}
3545

36-
// Make will resolve the dependency and return a appropriate concrete of the given abstraction.
37-
// It can take an abstraction (interface reference) and fill it with the related implementation.
38-
// It also can takes a function (receiver) with one or more arguments of the abstractions (interfaces) that need to be
39-
// resolved, Container will invoke the receiver function and pass the related implementations.
40-
// Deprecated: Make is deprecated.
41-
func Make(receiver interface{}) error {
42-
return container.Make(receiver)
43-
}
44-
4546
// Call takes a function with one or more arguments of the abstractions (interfaces) that need to be
4647
// resolved, Container will invoke the receiver function and pass the related implementations.
4748
func Call(receiver interface{}) error {
4849
return container.Call(receiver)
4950
}
5051

51-
// Bind takes an abstraction (interface reference) and fill it with the related implementation.
52-
func Bind(receiver interface{}) error {
53-
return container.Bind(receiver)
52+
// Resolve takes an abstraction (interface reference) and fill it with the related implementation.
53+
func Resolve(abstraction interface{}) error {
54+
return container.Resolve(abstraction)
55+
}
56+
57+
// NamedResolve resolves like the Resolve method but for named bindings.
58+
func NamedResolve(abstraction interface{}, name string) error {
59+
return container.NamedResolve(abstraction, name)
5460
}
5561

5662
// Fill takes a struct and fills the fields with the tag `container:"inject"`

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/golobby/container/v2
1+
module github.com/golobby/container/v3
22

33
go 1.11
44

0 commit comments

Comments
 (0)