golang不到30行代码实现依赖注入的方法

  

本文介绍了golang不到30行代码实现依赖注入的方法,分享给大家,具体如下:

  

<强>项目地址
  

  

go-di-demo   

<强>本项目依赖
  

  

使用标准库实现,无额外依赖

  

<强>依赖注入的优势
  

  

用java的人对春天于框架一定不会陌生,春天核心就是一个国际奥委会(控制反转/依赖注入)容器,带来一个很大的优势是解耦的。一般只依赖容器,而不依赖具体的类,当你的类有修改时,最多需要改动一下容器相关代码,业务代码并不受影响。

  

<强> golang的依赖注入原理
  

  

总的来说和java的差不多,步骤如下:(golang不支持动态创建对象,所以需要先手动创建对象然后注入,java可以直接动态创建对象)

  
      <李>通过反射读取对象的依赖(golang是通过标签实现)   <李>在容器中查找有无该对象实例   <李>如果有该对象实例或者创建对象的工厂方法,则注入对象或使用工厂创建对象并注入李   <李>如果无该对象实例,则报错李   
  

<强>代码实现
  

  

一个典型的容器实现如下,依赖类型参考了春天的单/原型,分别对象单例对象和实例对象:

        包迪      导入(   “同步”   “反映”   “fmt”   “弦”   “错误”   )      var (   ErrFactoryNotFound=错误。新(“未找到的工厂”)   )      接口类型工厂=func()({},错误)//容器   式集装箱结构{   sync.Mutex   单件map [string]接口{}   工厂map [string]工厂   }//容器实例化   func NewContainer容器()* {   返回,容器{   单例:{})(map [string]接口,   工厂:使(map [string]工厂),   }   }//注册单例对象   func (p *容器)SetSingleton(名称字符串,单界面{}){   p.Lock ()   p。单例[名字]=单例   p.Unlock ()   }//获取单例对象   func (p *容器)GetSingleton(名称字符串)接口{}{   返回p.singletons[名称]   }//获取实例对象   func (p *容器)GetPrototype(名称字符串)(接口{},错误){   工厂,好:=p.factories[名称]   如果!好{   返回nil, ErrFactoryNotFound   }   返回工厂()   }//设置实例对象工厂   func (p *容器)SetPrototype(名称字符串,工厂工厂){   p.Lock ()   p。工厂[名字]=工厂   p.Unlock ()   }//注入依赖   func (p *容器)保证({})实例接口错误{   elemType:=reflect.TypeOf(实例).Elem ()   避署:=reflect.ValueOf(实例).Elem ()   我:=0;我& lt;elemType.NumField ();我+ +{//遍历字段   fieldType:=elemType.Field(我)   标签:=fieldType.Tag.Get (di)//获取标签   diName:=p.injectName(标签)   如果diName==" {   继续   }   var (   diInstance接口{}   犯错的错误   )   如果p.isSingleton(标签){   diInstance=p.GetSingleton (diName)   }   如果p.isPrototype(标签){   diInstance呃=p.GetPrototype (diName)   }   如果犯错!=nil {   返回错   }   如果diInstance==nil {   返回错误。新(diName +“依赖未找到”)   }   ele.Field(我)这里(reflect.ValueOf (diInstance))   }   返回nil   }//获取需要注入的依赖名称   func (p *容器)injectName字符串(标记字符串){   标签:=字符串。分割(标签,",")   如果len(标签)==0 {   返回"   }   返回标签[0]   }//检测是否单例依赖   func (p *容器)isSingleton(标记字符串)bool {   标签:=字符串。分割(标签,",")   _,名字:=范围标记{   如果name==霸汀眥   返回假   }   }   还真   }//检测是否实例依赖   func (p *容器)isPrototype(标记字符串)bool {   标签:=字符串。分割(标签,",")   _,名字:=范围标记{   如果name==霸汀眥   还真   }   }   返回假   }//打印容器内部实例   func (p *容器)字符串String () {   行:=([]字符串,0,len (p.singletons) + len (p.factories) + 2)   行=append(线,“单例:”)   名称、项:=p。单件{   :=fmt。Sprintf (“% s: % x % s”,名字,和项目,reflect.TypeOf(项).String ())   行=append(线、线)   }   行=append(线,“工厂:”)   名称、项:=p。工厂{   :=fmt。Sprintf (“% s: % x % s”,名字,和项目,reflect.TypeOf(项).String ())   行=append(线、线)   }   返回字符串。加入(线、“\ n”)   }      

golang不到30行代码实现依赖注入的方法