亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

golang不到30行代碼實現依賴注入的方法

2020-04-01 18:55:33
字體:
來源:轉載
供稿:網友

本文介紹了golang不到30行代碼實現依賴注入的方法,分享給大家,具體如下:

項目地址

go-di-demo

本項目依賴

使用標準庫實現,無額外依賴

依賴注入的優勢

用java的人對于spring框架一定不會陌生,spring核心就是一個IoC(控制反轉/依賴注入)容器,帶來一個很大的優勢是解耦。一般只依賴容器,而不依賴具體的類,當你的類有修改時,最多需要改動一下容器相關代碼,業務代碼并不受影響。

golang的依賴注入原理

總的來說和java的差不多,步驟如下:(golang不支持動態創建對象,所以需要先手動創建對象然后注入,java可以直接動態創建對象)

  • 通過反射讀取對象的依賴(golang是通過tag實現)
  • 在容器中查找有無該對象實例
  • 如果有該對象實例或者創建對象的工廠方法,則注入對象或使用工廠創建對象并注入
  • 如果無該對象實例,則報錯

代碼實現

一個典型的容器實現如下,依賴類型參考了spring的singleton/prototype,分別對象單例對象和實例對象:

package diimport ( "sync" "reflect" "fmt" "strings" "errors")var ( ErrFactoryNotFound = errors.New("factory not found"))type factory = func() (interface{}, error)// 容器type Container struct { sync.Mutex singletons map[string]interface{} factories map[string]factory}// 容器實例化func NewContainer() *Container { return &Container{  singletons: make(map[string]interface{}),  factories: make(map[string]factory), }}// 注冊單例對象func (p *Container) SetSingleton(name string, singleton interface{}) { p.Lock() p.singletons[name] = singleton p.Unlock()}// 獲取單例對象func (p *Container) GetSingleton(name string) interface{} { return p.singletons[name]}// 獲取實例對象func (p *Container) GetPrototype(name string) (interface{}, error) { factory, ok := p.factories[name] if !ok {  return nil, ErrFactoryNotFound } return factory()}// 設置實例對象工廠func (p *Container) SetPrototype(name string, factory factory) { p.Lock() p.factories[name] = factory p.Unlock()}// 注入依賴func (p *Container) Ensure(instance interface{}) error { elemType := reflect.TypeOf(instance).Elem() ele := reflect.ValueOf(instance).Elem() for i := 0; i < elemType.NumField(); i++ { // 遍歷字段  fieldType := elemType.Field(i)  tag := fieldType.Tag.Get("di") // 獲取tag  diName := p.injectName(tag)  if diName == "" {   continue  }  var (   diInstance interface{}   err  error  )  if p.isSingleton(tag) {   diInstance = p.GetSingleton(diName)  }  if p.isPrototype(tag) {   diInstance, err = p.GetPrototype(diName)  }  if err != nil {   return err  }  if diInstance == nil {   return errors.New(diName + " dependency not found")  }  ele.Field(i).Set(reflect.ValueOf(diInstance)) } return nil}// 獲取需要注入的依賴名稱func (p *Container) injectName(tag string) string { tags := strings.Split(tag, ",") if len(tags) == 0 {  return "" } return tags[0]}// 檢測是否單例依賴func (p *Container) isSingleton(tag string) bool { tags := strings.Split(tag, ",") for _, name := range tags {  if name == "prototype" {   return false  } } return true}// 檢測是否實例依賴func (p *Container) isPrototype(tag string) bool { tags := strings.Split(tag, ",") for _, name := range tags {  if name == "prototype" {   return true  } } return false}// 打印容器內部實例func (p *Container) String() string { lines := make([]string, 0, len(p.singletons)+len(p.factories)+2) lines = append(lines, "singletons:") for name, item := range p.singletons {  line := fmt.Sprintf(" %s: %x %s", name, &item, reflect.TypeOf(item).String())  lines = append(lines, line) } lines = append(lines, "factories:") for name, item := range p.factories {  line := fmt.Sprintf(" %s: %x %s", name, &item, reflect.TypeOf(item).String())  lines = append(lines, line) } return strings.Join(lines, "/n")}
  • 最重要的是Ensure方法,該方法掃描實例的所有export字段,并讀取di標簽,如果有該標簽則啟動注入。
  • 判斷di標簽的類型來確定注入singleton或者prototype對象

測試

  1. 單例對象在整個容器中只有一個實例,所以不管在何處注入,獲取到的指針一定是一樣的。
  2. 實例對象是通過同一個工廠方法創建的,所以每個實例的指針不可以相同。

下面是測試入口代碼,完整代碼在github倉庫,有興趣的可以翻閱:

package mainimport ( "di" "database/sql" "fmt" "os" _ "github.com/go-sql-driver/mysql" "demo")func main() { container := di.NewContainer() db, err := sql.Open("mysql", "root:root@tcp(localhost)/sampledb") if err != nil {  fmt.Printf("error: %s/n", err.Error())  os.Exit(1) } container.SetSingleton("db", db) container.SetPrototype("b", func() (interface{}, error) {  return demo.NewB(), nil }) a := demo.NewA() if err := container.Ensure(a); err != nil {  fmt.Println(err)  return } // 打印指針,確保單例和實例的指針地址 fmt.Printf("db: %p/ndb1: %p/nb: %p/nb1: %p/n", a.Db, a.Db1, &a.B, &a.B1)}

執行之后打印出來的結果為:

db: 0xc4200b6140
db1: 0xc4200b6140
b: 0xc4200a0330
b1: 0xc4200a0338

可以看到兩個db實例的指針一樣,說明是同一個實例,而兩個b的指針不同,說明不是一個實例。

寫在最后

通過依賴注入可以很好的管理多個對象之間的實例化以及依賴關系,配合配置文件在應用初始化階段將需要注入的實例注冊到容器中,在應用的任何地方只需要在實例化時注入容器即可。沒有額外依賴。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一网站男人都懂| 亚洲成人网久久久| 伊人久久久久久久久久久| 国产亚洲欧美日韩美女| 青草热久免费精品视频| 日韩欧美有码在线| 国产综合色香蕉精品| 欧美疯狂xxxx大交乱88av| 久久成人18免费网站| 亚洲综合自拍一区| 国产91精品最新在线播放| 精品自在线视频| 亚洲精品久久久久久久久久久久久| 久久深夜福利免费观看| 亚洲最大av网站| 中文.日本.精品| 91久久久久久久久久久久久| 亚洲免费视频在线观看| 国产精品亚洲一区二区三区| 亚洲美女动态图120秒| 最新国产精品亚洲| 狠狠躁夜夜躁人人爽超碰91| 美女扒开尿口让男人操亚洲视频网站| 久久香蕉频线观| 91精品视频一区| 国产成+人+综合+亚洲欧洲| 欧美国产日产韩国视频| 成人在线一区二区| 日韩av三级在线观看| 亚州成人av在线| 亚洲精品99久久久久中文字幕| 668精品在线视频| 中文字幕亚洲欧美日韩高清| 色天天综合狠狠色| 国产91对白在线播放| 97久久精品视频| 亚洲精品电影久久久| 欧美日韩国产成人在线观看| 亚洲无亚洲人成网站77777| 色中色综合影院手机版在线观看| 丝袜美腿精品国产二区| 欧美精品一区在线播放| 中文亚洲视频在线| 91网在线免费观看| 国产91色在线|免| 日韩成人网免费视频| 黑人巨大精品欧美一区二区三区| 最近中文字幕2019免费| 国产在线观看精品一区二区三区| 国产一区二区三区精品久久久| 欧美激情亚洲激情| 亚洲精品国产综合久久| 亚洲国产99精品国自产| 日本精品免费一区二区三区| 一区二区欧美激情| 亚洲精品日韩丝袜精品| 一道本无吗dⅴd在线播放一区| 一区二区日韩精品| 亚洲电影免费在线观看| 欧美有码在线观看视频| 久久综合免费视频影院| 国产欧美日韩中文字幕| 久久综合网hezyo| 国产又爽又黄的激情精品视频| 亚洲一级黄色av| 亚洲三级黄色在线观看| 久久免费观看视频| 日本精品性网站在线观看| 国产成人精品a视频一区www| 亚洲自拍小视频| 国产精品久久久久久影视| 日韩av资源在线播放| 自拍偷拍免费精品| 懂色aⅴ精品一区二区三区蜜月| 一夜七次郎国产精品亚洲| 国产狼人综合免费视频| 欧美亚洲伦理www| 中文字幕欧美精品日韩中文字幕| 91丝袜美腿美女视频网站| 在线播放日韩精品| 色偷偷噜噜噜亚洲男人的天堂| 日韩毛片在线看| 亚洲高清免费观看高清完整版| 黄色一区二区在线| 久久视频中文字幕| 在线日韩日本国产亚洲| 日韩有码片在线观看| 亚洲高清不卡av| 中文字幕久热精品在线视频| 欧美一区二区.| 欧美国产日韩中文字幕在线| 亚洲综合成人婷婷小说| 国产在线视频一区| 麻豆乱码国产一区二区三区| 91九色在线视频| 国产亚洲精品美女久久久| 国产97免费视| 免费91在线视频| 91视频-88av| 亚洲激情第一页| 国产精品久久久久99| 青草热久免费精品视频| 久久av资源网站| 精品国产电影一区| 日本午夜人人精品| 在线播放国产一区中文字幕剧情欧美| 一本一本久久a久久精品综合小说| 国产精品成av人在线视午夜片| 久久综合九色九九| 69国产精品成人在线播放| 欧美激情奇米色| 亚洲一区二区免费在线| 成人网欧美在线视频| 日韩精品极品在线观看播放免费视频| 久久久久久久久电影| 欧美怡红院视频一区二区三区| 欧美精品18videosex性欧美| 国产精品中文在线| 欧美亚洲午夜视频在线观看| 欧美韩日一区二区| 97视频国产在线| 亚洲美女激情视频| 永久免费看mv网站入口亚洲| 日韩精品999| 久久理论片午夜琪琪电影网| 亚洲精品自拍第一页| 国产精品高潮在线| 成人黄色在线观看| 欧美日韩成人精品| 欧美激情在线狂野欧美精品| 欧美日韩在线观看视频小说| 日本aⅴ大伊香蕉精品视频| 黑人巨大精品欧美一区二区免费| 韩国精品美女www爽爽爽视频| 日韩成人av网| 日韩美女视频免费在线观看| 亚洲精选中文字幕| 91视频国产一区| 国产在线一区二区三区| 午夜精品一区二区三区在线播放| 国产91精品久| 久久99久久亚洲国产| 久久免费国产视频| 成人福利在线观看| 国产日韩欧美影视| 日韩精品在线观看一区二区| 亚洲色图日韩av| 欧美成aaa人片免费看| 日韩精品小视频| 色777狠狠综合秋免鲁丝| 久久电影一区二区| 久久九九亚洲综合| 欧美黑人xxx| 米奇精品一区二区三区在线观看| 欧美肥臀大乳一区二区免费视频| 国产一区二区丝袜| 亚洲春色另类小说| 国产在线观看不卡| 91天堂在线视频| 国产精品wwww| 亚洲人成网站777色婷婷| 岛国av在线不卡| 日韩成人在线免费观看| 国产精品久久一|