欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang輕量級IoC容器安裝使用示例

 更新時間:2022年06月24日 08:35:59   作者:深藍studyzy  
這篇文章主要為大家介紹了Golang輕量級IoC容器安裝使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

1. iocgo簡介

習慣于Java或者C#開發(fā)的人應(yīng)該對控制反轉(zhuǎn)與依賴注入應(yīng)該再熟悉不過了。在Java平臺有鼎鼎大名的Spring框架,在C#平臺有Autofac,Unity,Windsor等,我當年C#開發(fā)時用的最多的就是Windsor。使用IoC容器是面向?qū)ο箝_發(fā)中非常方便的解耦模塊之間的依賴的方法。各個模塊之間不依賴于實現(xiàn),而是依賴于接口,然后在構(gòu)造函數(shù)或者屬性或者方法中注入特定的實現(xiàn),方便了各個模塊的拆分以及模塊的獨立單元測試。

在[長安鏈]的設(shè)計中,各個模塊可以靈活組裝,模塊之間的依賴基于protocol中定義的接口,每個接口有一個或者多個官方實現(xiàn),當然第三方也可以提供該接口更多的實現(xiàn)。為了實現(xiàn)更靈活的組裝各個模塊,管理各個模塊的依賴關(guān)系,于是我寫了iocgo這個輕量級的golang版Ioc容器。

2. iocgo如何使用

2.1 iocgo包的安裝

現(xiàn)在go官方版本已經(jīng)出到1.17了,當然我在代碼中其實也沒有用什么新版本的新特性,于是就用1.15版本或者之后的Go版本即可。要使用iocgo包,直接通過go get添加到項目中:

go get github.com/studyzy/iocgo

2.2 使用示例與說明

2.2.1 最簡單的例子:

type Fooer interface {
	Foo(int)
}
type Foo struct {
}
func (Foo)Foo(i int)  {
	fmt.Println("foo:",i)
}
type Barer interface {
	Bar(string)
}
type Bar struct {
}
func (Bar) Bar(s string){
	fmt.Println("bar:",s)
}
type Foobarer interface {
	Say(int,string)
}
type Foobar struct {
	foo Fooer
	bar Barer
}
func NewFoobar(f Fooer,b Barer) Foobarer{
	return &Foobar{
		foo: f,
		bar: b,
	}
}
func (f Foobar)Say(i int ,s string)  {
	f.foo.Foo(i)
	f.bar.Bar(s)
}
func TestContainer_SimpleRegister(t *testing.T) {
	container := NewContainer()
	container.Register(NewFoobar)
	container.Register(func() Fooer { return &Foo{} })
	container.Register(func() Barer { return &Bar{} })
	var fb Foobarer
	container.Resolve(&fb)
	fb.Say(123,"Hello World")
}

這里我使用NewContainer()創(chuàng)建了一個新的容器,然后在容器中調(diào)用Register方法注冊了3個接口和對應(yīng)的構(gòu)造函數(shù),分別是:

  • Foobarer接口對應(yīng)NewFoobar(f Fooer,b Barer)構(gòu)造函數(shù)
  • Fooer接口對應(yīng)構(gòu)造&Foo{}的匿名函數(shù)。
  • Barer接口對應(yīng)構(gòu)造&Bar{}的匿名函數(shù)。

接下來調(diào)用Resolve函數(shù),并傳入var fb Foobarer 這個接口變量的指針,iocgo就會自動去構(gòu)建Foobarer對應(yīng)的實例,并最終將實例賦值到fb這個變量上,于是最后我們就可以正常調(diào)用fb.Say實例方法了。

2.22. Register 的選項

iocgo的注冊interface到對象的函數(shù)定義如下:

func Register(constructor interface{}, options ...Option) error

iocgo為Register函數(shù)提供了以下參數(shù)選項可根據(jù)實際情況選擇性使用:

  • Name 為某個interface->對象的映射命名
  • Optional 表名這個構(gòu)造函數(shù)中哪些注入的interface參數(shù)是可選的,如果是可選,那么就算找不到interface對應(yīng)的實例也不會報錯。
  • Interface 顯式聲明這個構(gòu)造函數(shù)返回的實例是映射到哪個interface。
  • Lifestyle(isTransient) 聲明這個構(gòu)造函數(shù)在構(gòu)造實例后是構(gòu)造的臨時實例還是單例實例,如果是臨時實例,那么下次再獲取該interface對應(yīng)的實例時需要再次調(diào)用構(gòu)造函數(shù),如果是單例,那么就緩存實例到容器中,下次再想獲得interface對應(yīng)的實例時直接使用緩存中的,不需要再次構(gòu)造。
  • DependsOn 這個主要是指定構(gòu)造函數(shù)中的某個參數(shù)在通過容器獲得對應(yīng)的實例時,應(yīng)該通過哪個Name去獲得對應(yīng)的實例。
  • Parameters 這個主要用于指定構(gòu)造函數(shù)中的某些非容器托管的參數(shù),比如某構(gòu)造函數(shù)中有int,string等參數(shù),而這些參數(shù)的實例是不需要通過ioc容器進行映射托管的,那么就在這里直接指定。
  • Default 這個主要用于設(shè)置一個interface對應(yīng)的默認的實例,也就是如果沒有指定Name的情況下,應(yīng)該找哪個實例。 關(guān)于每一個參數(shù)該如何使用,我都寫了UT樣例,具體參考: container_test.go

2.2.3. 注冊實例

如果我們已經(jīng)有了某個對象的實例,那么可以將該實例和其想映射的interface直接注冊到ioc容器中,方便其他依賴的對象獲取,RegisterInstance函數(shù)定義如下:

RegisterInstance(interfacePtr interface{}, instance interface{}, options ...Option) error 

使用上也很簡單,直接將實例對應(yīng)的interface的指針作為參數(shù)1,實例本身作為參數(shù)2,傳入RegisterInstance即可:

b := &Bar{}
var bar Barer //interface
container.RegisterInstance(&bar, b) // register interface -> instance

2.2.4. 獲得實例

相關(guān)映射我們通過Register函數(shù)和RegisterInstance函數(shù)已經(jīng)注冊到容器中,接下來就需要從容器獲得指定的實例了。獲得實例需要調(diào)用函數(shù):

func Resolve(abstraction interface{}, options ...ResolveOption) error

這里第一個參數(shù)abstraction是我們想要獲取的某個interface的指針,第二個參數(shù)是可選參數(shù),目前提供的選項有:

  • ResolveName 指定使用哪個name的interface和實例的映射,如果不指定,那么就是默認映射。
  • Arguments 指定在調(diào)用對應(yīng)的構(gòu)造函數(shù)獲得實例時,傳遞的參數(shù),比如int,string等類型的不在ioc容器中托管的參數(shù),可以在這里指定。如果構(gòu)造函數(shù)本身需要這些參數(shù),而且在前面Register的時候已經(jīng)通過Parameters選項進行了指定,那么這里新的指定會覆蓋原有Register的指定。
var fb Foobarer
err:=container.Resolve(&fb)

另外如果我們的構(gòu)造函數(shù)return的值中支持error,而且實際構(gòu)造的時候確實返回了error,那么Resolve函數(shù)也會返回對應(yīng)的這個err。

特別注意:Resolve的第一個參數(shù)是申明的某個interface的指針,一定要是指針,不能直接傳interface

2.2.5. 結(jié)構(gòu)體參數(shù)和字段填充

有些時候構(gòu)造函數(shù)的入?yún)⒎浅6?,于是我們可以申明一個結(jié)構(gòu)體,把所有入?yún)⒍挤湃脒@個結(jié)構(gòu)體中,這樣構(gòu)造函數(shù)就只需要一個參數(shù)了。iocgo也支持自動填充這個結(jié)構(gòu)體中interface對應(yīng)的實例,從而構(gòu)造新的對象。另外iocgo也提供了Fill方法,可以直接填充某個結(jié)構(gòu)體,比如:

type FoobarInput struct {
	foo Fooer
	bar Barer
	msg string
}
input := FoobarInput{
		msg: "studyzy",
	}
	container.Register(func() Fooer { return &Foo{} })
	container.Register(func() Barer { return &Bar{} })
	err := container.Fill(&input)

結(jié)構(gòu)體中的字段還支持tag,目前提供的tag有兩種:

  • name //指定這個字段在獲得對應(yīng)的實例時使用的name
  • optional //指定這個字段是否是可選的,如果是,那么就算獲得不到對應(yīng)的實例,也不會報錯。 示例example:
type FoobarInputWithTag struct {
	foo Fooer `optional:"true"`
	bar Barer `name:"baz"`
	msg string
}

2.2.6. 函數(shù)調(diào)用

除了構(gòu)造函數(shù)注入之外,iocgo也支持函數(shù)注入,我們申明一個函數(shù),這個函數(shù)的參數(shù)中有些參數(shù)是interface,那么通過調(diào)用iocgo中的Call方法,可以為這個函數(shù)注入對應(yīng)的實例作為參數(shù),并最終完成函數(shù)的調(diào)用。 示例 example:

func SayHi1(f Fooer, b Barer) {
	f.Foo(1234)
	b.Bar("hi")
}
Register(func() Fooer { return &Foo{} })
Register(func() Barer { return &Bar{} })
Call(SayHi1)

Call函數(shù)也是支持選項的,目前提供了2個選項:

  • CallArguments 指定函數(shù)中某個參數(shù)的值
  • CallDependsOn 指定函數(shù)中某個參數(shù)在通過ioc容器獲得實例時使用哪個name來獲得實例。 最后函數(shù)調(diào)用完成,如果函數(shù)本身有多個返回值,有error返回,那么Call函數(shù)也會返回對應(yīng)的結(jié)果。

2.3 參考:

在寫這個iocgo的代碼時,主要參考了以下兩個Ioc相關(guān)的項目:

3. 總結(jié)

iocgo是一個純Golang語言開發(fā)的用于管理依賴注入的IoC容器,使用這個容器可以很好的實現(xiàn)go語言下的面向?qū)ο箝_發(fā),模塊解耦?,F(xiàn)已經(jīng)開源,歡迎大家使用,開源地址:https://github.com/studyzy/iocgo

以上就是Golang輕量級IoC容器安裝使用示例的詳細內(nèi)容,更多關(guān)于Golang輕量級IoC容器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文詳解kubernetes?中資源分配的那些事

    一文詳解kubernetes?中資源分配的那些事

    這篇文章主要為大家介紹了kubernetes?中資源分配的那些事,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • Windows+Linux系統(tǒng)下Go語言環(huán)境安裝配置過程

    Windows+Linux系統(tǒng)下Go語言環(huán)境安裝配置過程

    Go 語言被設(shè)計成一門應(yīng)用于搭載 Web 服務(wù)器,存儲集群或類似用途的巨型中央服務(wù)器的系統(tǒng)編程語言。這篇文章主要介紹了Windows+Linux系統(tǒng)下Go語言環(huán)境搭建配置過程,針對每種系統(tǒng)給大家講解的非常詳細,需要的朋友可以參考下
    2021-06-06
  • 詳解如何使用Golang擴展Envoy

    詳解如何使用Golang擴展Envoy

    這篇文章主要為大家介紹了詳解如何使用Golang擴展Envoy實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • golang中接口對象的轉(zhuǎn)型兩種方式

    golang中接口對象的轉(zhuǎn)型兩種方式

    這篇文章主要介紹了golang中接口對象的轉(zhuǎn)型方式,大家都知道接口對象的轉(zhuǎn)型有兩種方式,文中通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2021-10-10
  • golang關(guān)閉chan通道的方法示例

    golang關(guān)閉chan通道的方法示例

    在go語言中,通道(channel)是一個非常重要的概念,通道提供了一種在不同 goroutine 之間安全地傳遞數(shù)據(jù)的方式,在本文中,我們將討論如何關(guān)閉通道以及在關(guān)閉通道時需要考慮的事項,需要的朋友可以參考下
    2024-02-02
  • Go?Redis客戶端使用的兩種對比

    Go?Redis客戶端使用的兩種對比

    這篇文章主要為大家介紹了Go?Redis客戶端使用對比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • gin使用自定義結(jié)構(gòu)綁定表單數(shù)據(jù)的示例代碼

    gin使用自定義結(jié)構(gòu)綁定表單數(shù)據(jù)的示例代碼

    這篇文章主要介紹了gin使用自定義結(jié)構(gòu)綁定表單數(shù)據(jù)的示例代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • 一文讀懂go中semaphore(信號量)源碼

    一文讀懂go中semaphore(信號量)源碼

    這篇文章主要介紹了一文讀懂go中semaphore(信號量)源碼的相關(guān)知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Golang 實現(xiàn) Redis系列(六)如何實現(xiàn) pipeline 模式的 redis 客戶端

    Golang 實現(xiàn) Redis系列(六)如何實現(xiàn) pipeline 模式的 redis 客戶端

    pipeline 模式的 redis 客戶端需要有兩個后臺協(xié)程負責 tcp 通信,調(diào)用方通過 channel 向后臺協(xié)程發(fā)送指令,并阻塞等待直到收到響應(yīng),本文是使用 golang 實現(xiàn) redis 系列的第六篇, 將介紹如何實現(xiàn)一個 Pipeline 模式的 Redis 客戶端。
    2021-07-07
  • go語言區(qū)塊鏈學習調(diào)用智能合約

    go語言區(qū)塊鏈學習調(diào)用智能合約

    這篇文章主要為大家介紹了go語言區(qū)塊鏈學習中如何調(diào)用智能合約的實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10

最新評論