欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品

主頁 > 知識庫 > golang不到30行代碼實現依賴注入的方法

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

熱門標簽:鄭州亮點科技用的什么外呼系統 釘釘有地圖標注功能嗎 建造者2地圖標注 黃岡人工智能電銷機器人哪個好 浙江高頻外呼系統多少錢一個月 惠州電銷防封電話卡 濱州自動電銷機器人排名 阿里云ai電話機器人 汕頭小型外呼系統

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

項目地址

go-di-demo

本項目依賴

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

依賴注入的優勢

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

golang的依賴注入原理

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

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

代碼實現

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

package di

import (
 "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 main

import (
 "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的指針不同,說明不是一個實例。

寫在最后

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

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

您可能感興趣的文章:
  • golang使用 gomodule 在公共測試環境管理go的依賴的實例詳解
  • 解決vscode中golang插件依賴安裝失敗問題
  • golang 如何自動下載所有依賴包

標簽:滄州 東營 泰安 昭通 駐馬店 瀘州 阿壩 晉中

巨人網絡通訊聲明:本文標題《golang不到30行代碼實現依賴注入的方法》,本文關鍵詞  golang,不到,30行,代碼,實現,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《golang不到30行代碼實現依賴注入的方法》相關的同類信息!
  • 本頁收集關于golang不到30行代碼實現依賴注入的方法的相關信息資訊供網民參考!
  • 推薦文章
    欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品
  • <rt id="w000q"><acronym id="w000q"></acronym></rt>
  • <abbr id="w000q"></abbr>
    <rt id="w000q"></rt>
    韩国无码一区二区三区精品| 欧美日韩一二三区| 久久影音资源网| 三级精品在线观看| 潘金莲一级淫片aaaaa| 色综合欧美在线| 国产精品久久久久久久久搜平片 | 喷水视频在线观看| 欧美亚洲国产怡红院影院| 国产精品久久久久久久岛一牛影视| 国产曰批免费观看久久久| 99久久精品免费视频 | 久久久国产精品久久久| 在线免费av一区| 一区二区三区小说| 逼特逼视频在线观看| 欧美一区二区三区四区在线观看| 亚洲高清久久久| 噜噜噜在线视频| 欧美不卡一区二区三区四区| 久久国产成人午夜av影院| 久久久久久久毛片| 国产日韩精品视频一区| 成人午夜视频在线观看| 在线观看日韩精品| 亚洲成人av中文| 免费看黄色的视频| 国产日产欧美一区二区三区| 国产suv精品一区二区6| 在线看不卡av| 亚洲成av人综合在线观看| 一本加勒比波多野结衣| 欧美精品一区二区三区高清aⅴ| 国内精品久久久久影院一蜜桃| 久久嫩草捆绑紧缚| 国产精品久久国产精麻豆99网站| 91丨porny丨国产入口| 777久久久精品| 久久电影网站中文字幕| 999精品视频在线观看播放| 亚洲欧美视频在线观看| 看全色黄大色黄女片18| 2020日本不卡一区二区视频| 国产成人精品亚洲日本在线桃色| 日本韩国精品在线| 日韩精品一二三区| 无码人中文字幕| 亚洲老司机在线| 国产美女喷水视频| 国产精品人人做人人爽人人添| av影院午夜一区| 日韩免费高清视频| 国产999精品久久久久久绿帽| 欧美综合一区二区| 美国av一区二区| 国产极品国产极品| 日韩精品一二三| 国产激情无码一区二区三区| 午夜久久久久久电影| 男女做爰猛烈刺激| 亚洲黄色在线视频| 日韩毛片无码永久免费看| 亚洲视频一二三| 国产精品扒开腿做爽爽| 专区另类欧美日韩| 久久只有这里有精品| 日韩美女视频一区二区| 欧美色图亚洲激情| 一区二区三区电影在线播| 亚洲欧洲久久久| 日本人亚洲人jjzzjjz| 无码人妻丰满熟妇啪啪欧美| 中文字幕中文字幕一区二区| 800av在线播放| 国产精品色噜噜| 久久久久9999| 日韩毛片在线免费观看| 亚洲av综合一区二区| 亚洲女爱视频在线| 国精品无码人妻一区二区三区| 亚洲欧美色图小说| 亚洲激情图片网| 婷婷一区二区三区| 色素色在线综合| 国内偷窥港台综合视频在线播放| 欧美日韩免费观看一区三区| 国产成人夜色高潮福利影视| 91精品国产手机| 亚洲精品无码久久久久久久| 欧美国产乱子伦| 好吊视频在线观看| 视频在线观看91| 欧美主播一区二区三区美女| 国产酒店精品激情| 精品理论电影在线观看 | 精品久久免费看| 日本黄色一级网站| 在线观看亚洲免费视频| 91网站黄www| 久久综合久久综合亚洲| 性活交片大全免费看| 日韩美女视频一区二区| 很污很黄的网站| 蜜桃精品在线观看| 欧美裸体bbwbbwbbw| 99久久久精品| 国产精品成人免费| 国产一区第一页| 国产一区二区三区在线观看免费 | 日韩欧美在线影院| 无码国产精品一区二区免费式直播| 国产精品国产三级国产三级人妇| 国内精品卡一卡二卡三| 青青国产91久久久久久| 欧美久久婷婷综合色| 制服下的诱惑暮生| 日韩理论片中文av| 久久久久久久久久久久久女过产乱| 国产一区二区在线视频| 久久久综合精品| 欧美大波大乳巨大乳| 久久国产精品无码网站| 精品99一区二区三区| 91精彩刺激对白露脸偷拍| 蜜桃精品视频在线| 精品免费视频.| 成人片黄网站色大片免费毛片| 日韩国产欧美在线播放| 日韩一区二区中文字幕| 中文字幕一区二区久久人妻网站| 午夜精品久久久久久久久久久| 欧美日高清视频| 中文字幕精品久久久| 蜜臀av一区二区| 久久久久久久性| 成人欧美一区二区三区黑人一| 国产不卡视频一区二区三区| 国产精品麻豆99久久久久久| 男女羞羞免费视频| 91麻豆自制传媒国产之光| 色屁屁草草影院ccyy.com| 另类综合日韩欧美亚洲| 久久久久国产免费免费| 99热6这里只有精品| 成人av电影观看| 亚洲一区二区三区中文字幕 | 不卡电影免费在线播放一区| 中文字幕日韩精品一区| 在线精品亚洲一区二区不卡| 国产乱淫av麻豆国产免费| 肉肉av福利一精品导航| 精品国精品自拍自在线| 日韩一区二区三区四区视频| 成人午夜激情在线| 夜夜亚洲天天久久| 日韩三级视频中文字幕| 久久午夜精品视频| 成人午夜伦理影院| 亚洲国产aⅴ成人精品无吗| 日韩美女视频一区二区在线观看| 调教驯服丰满美艳麻麻在线视频| 懂色av一区二区三区免费看| 一区二区三区四区视频精品免费 | 在线成人av影院| 一区二区三区久久久久| 成人黄色一级视频| 亚洲成人资源网| 精品国产乱码久久久久久夜甘婷婷 | 成人午夜在线免费| 亚洲福利视频一区二区| 久久综合国产精品| 色综合视频一区二区三区高清| 青青草视频网站| 国产精品一区一区| 一区二区三区在线看| 精品日韩在线观看| 国产探花在线播放| 精品国产av色一区二区深夜久久| 国产精品一区二区三区网站| 亚洲最快最全在线视频| 欧美精品一区二| 在线观看一区日韩| 亚洲精品午夜视频| 91免费版pro下载短视频| 狂野欧美性猛交blacked| 亚洲欧美综合另类在线卡通| 337p亚洲精品色噜噜噜| 五月天色婷婷丁香| 日本黄色免费观看| k8久久久一区二区三区| 美脚の诱脚舐め脚责91 | 狠狠色丁香婷婷综合久久片| 中文字幕一区二区三区av| 欧美一级片在线| 国产成人无码aa精品一区| 中文字幕在线免费看线人| av不卡免费在线观看| 久久精品国产免费看久久精品| 中文字幕亚洲区| 2020日本不卡一区二区视频|