CRCMS

高山仰止,景行行止,虽不能至,心向往之

大道至简


Golang Ioc容器

简介

用惯了LaravelIoc,对象获取变得那么自然,初用Go,各struct,func都要自己解析
一堆NewFunc,索性自己搞了个ioc
参见Github(https://github.com/firmeve/firmeve)

对象绑定

1
f := NewFirmeve()

标量绑定

1
f.Bind(`bool`, false)
1
f.Bind(`string`, "string")

Struct 绑定

假设我们有如下struct

1
2
3
4
5
6
7
type Foo struct {
Bar string
}

func NewFoo(bar string) Foo{
return Foo{Bar:bar}
}

我们将foo绑定进我们的容器中

1
f.Bind(`foo`,NewFoo("abc"))

Prt 绑定

绑定prtstruct类型是我们最常用的一种方式,请看下面的示例

1
2
3
4
5
6
7
8
9
type Baz struct {
Baz string
}

func NewBaz() *Baz {
return &Baz{}
}

f.Bind(`baz`, NewBaz())

函数绑定

1
2
3
4
5
func NewFoo() Foo{
return Foo{Bar:"default string"}
}

f.Bind(`foo`, NewFoo)

使用Firmeve在绑定的时候暂时不支持参数注入
注意:如果是非函数类型绑定,则会默认为单实例类型

已绑定值覆盖

我们通过WithBindCover(true)方法可以轻松设定覆盖参数

1
2
3
4
f.Bind(`bool`, false)
fmt.Printf("%t",f.Get(`bool`))
f.Bind(`bool`, true, WithBindCover(true))
fmt.Printf("%t",f.Get(`bool`))

对象获取

验证对象是否存在

在不确定容器中是否包含此对象时,请使用Has方法进行判断

1
f.Has(`foo`)

对象获取

直接获取容器中的值

1
f.Get(`foo`)

注意:如果指的定的key不存在,则会抛出panic错误

新对象获取

1
2
3
4
5
6
7
8
func NewFoo() Foo{
return Foo{Bar:"default string"}
}

f.Bind(`foo`, NewFoo)
fmt.Printf("%p\n",f.Get("foo"))
fmt.Printf("%p\n",f.Get("foo"))
fmt.Printf("%p\n",f.Get("foo"))

Firmeve中,如果需要每次重新得到一个新的结构体对象
必须绑定一个函数值,否则得到的将是一个单实例

单例获取

1
2
3
4
5
6
7
8
func NewFoo() Foo{
return Foo{Bar:"default string"}
}

f.Bind(`foo`, NewFoo())
fmt.Printf("%p\n",f.Get("foo"))
fmt.Printf("%p\n",f.Get("foo"))
fmt.Printf("%p\n",f.Get("foo"))

参数解析

函数自动解析

让我们来看一个简单的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type PersonName struct {
Name string
}

func NewPersonName() PersonName {
return PersonName{Name: "Firmeve"}
}

type PersonAge struct {
Age int
}

func PersonAge() *PersonAge {
return &PersonAge{Age: 1}
}

type Person struct {
name PersonName
age *PersonAge
}

func NewPerson(name PersonName,age *PersonAge) *NewPerson {
return NewPerson{
name: name
age: age
}
}

f.Bind("PersonName", NewPersonName)
f.Bind("PersonAge", PersonAge)
fmt.Printf("%#v", f.Resolve(NewPerson))

结构体tag自动解析

现在,让我们修改下上面的Person

1
2
3
4
5
type Person struct {
Name PersonName `inject:"PersonName"`
Age *PersonAge `inject:"PersonAge"`
age1 *PersonAge `inject:"PersonAge"`
}

然后我们使用new函数直接创建一个新的结构体指针

1
fmt.Printf("%#v", new(NewPerson))

注意:此时 Person中的Name字段并不是指针类型,而age1不符合structtag规范,所以Firmeve都会自动忽略。