版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第浅析golang的依赖注入目录前言基于反射的DI基于代码生成的DI
前言
如果是做web开发,对依赖注入肯定不陌生,java程序员早就习惯了spring提供的依赖注入,做业务开发时非常方便,只关注业务逻辑即可,对象之间的依赖关系都交给框架。
golang是强类型语言,编译后是机器码,所以一般使用反射或代码生成解决依赖注入的问题
基于反射的DI
基于反射解决DI问题的框架,使用比较多的是Uber的dig库
官方的例子:
typeConfigstruct{
Prefixstring
//初始化Config函数
funcNewConfig()(*Config,error){
//Inarealprogram,theconfigurationwillprobablybereadfroma
//file.
varcfgConfig
err:=json.Unmarshal([]byte(`{"prefix":"[foo]"}`),cfg)
returncfg,err
//初始化logger函数
funcNewLogger(cfg*Config)*log.Logger{
returnlog.New(os.Stdout,cfg.Prefix,0)
funcHandle()(l*log.Logger){
l.Print("You'vebeeninvoked")
funcmain(){
//初始化dig对象
c:=dig.New()
//Provide方法用来设置依赖的对象
er:=c.Provide(NewConfig)
iferr!=nil{
panic(err)
//设置依赖的对象
err=c.Provide(NewLogger)
iferr!=nil{
panic(err)
//执行Handle()方法
//Handle依赖Config和Logger,使用Invoke执行方法时会自动注入依赖(依赖的对象要传入Provide方法中)
err=c.Invoke(Handle)
iferr!=nil{
panic(err)
//Output:
//[foo]You'vebeeninvoked
}
dig提供了一个容器(container),所有的依赖项通过Provide方法添加,执行某个方法时使用Invoke方法,该方法会自动注入所需要的依赖。
dig使用反射机制解决DI问题,所以代码执行性能上会有损耗
并且因为使用反射所以可能出现编译时没有错误,执行时报空指针
详情使用方法可以参考官方文档,dig可以继承到gin框架中,有兴趣的可以看看资料。
笔者不太喜欢这种使用方式,为了依赖注入破坏了代码原有的调用方式。
基于代码生成的DI
wire库是google出的解决golangDI问题的工具,它可以自动生成依赖注入的代码,节省了手动去处理依赖关系
github地址
wire对原有代码的侵入度很低,开发过程中,在依赖注入代码处调用Build方法(例子中是初始化controller对象)就可以了
//+buildwireinject
packagemain
import(
"encoding/json"
"fmt"
"/google/wire"
"net/http"
typeDataSourcestruct{
Operationstring
funcNewDataSource()DataSource{
returnDataSource{Operation:"operation_name"}
//==================
typeDaostruct{
DataSourceDataSource
funcNewDao(dsDataSource)*Dao{
returnDao{
DataSource:ds,
func(d*Dao)GetItemList()([]string,error){
//TODO拿到DB对象做查询操作
fmt.Printf("dbobject:%s",d.DataSource.Operation)
return[]string{d.DataSource.Operation,"item1","item2"},nil
//====================
typeServicestruct{
Dao*Dao
funcNewService(dao*Dao)*Service{
returnService{Dao:dao}
func(s*Service)GetItemList()([]string,error){
returns.Dao.GetItemList()
//=====================
typeControllerstruct{
Service*Service
funcNewController(service*Service)*Controller{
returnController{Service:service}
func(c*Controller)GetItemList()([]string,error){
returnc.Service.GetItemList()
varMegaSet=wire.NewSet(NewDataSource,NewDao,NewService,NewController)
funcinitializeController()*Controller{
wire.Build(MegaSet)
returnController{}
funcgetItemList(whttp.ResponseWriter,r*http.Request){
controller:=initializeController()
itemList,_:=controller.GetItemList()
output,_:=json.Marshal(itemList)
fmt.Fprintf(w,string(output))
funcmain(){
http.HandleFunc("/items",getItemList)
err:=http.ListenAndServe(":8080",nil)
iferr!=nil{
panic(err)
}
然后再项目根目录执行wire命令,会生成构建好依赖关系的代码(以_gen结尾的文件)
//CodegeneratedbyWire.DONOTEDIT.
//go:generategorun/google/wire/cmd/wire
//+build!wireinject
packagemain
import(
"encoding/json"
"fmt"
"/google/wire"
"net/http"
//Injectorsfrommain.go:
//此处是生成的代码
funcinitializeController()*Controller{
dataSource:=NewDataSource()
dao:=NewDao(dataSource)
service:=NewService(dao)
controller:=NewController(service)
returncontroller
//main.go:
typeDataSourcestruct{
Operationstring
funcNewDataSource()DataSource{
returnDataSource{Operation:"operation_name"}
typeDaostruct{
DataSourceDataSource
funcNewDao(dsDataSource)*Dao{
returnDao{
DataSource:ds,
func(d*Dao)GetItemList()([]string,error){
fmt.Printf("dbobject:%s",d.DataSource.Operation)
return[]string{d.DataSource.Operation,"item1","item2"},nil
typeServicestruct{
Dao*Dao
funcNewService(dao*Dao)*Service{
returnService{Dao:dao}
func(s*Service)GetItemList()([]string,error){
returns.Dao.GetItemList()
typeControllerstruct{
Service*Service
funcNewController(service*Service)*Controller{
returnController{Service:service}
func(c*Controller)GetItemList()([]string,error){
returnc.Service.GetItemList()
varMegaSet=wire.NewSet(NewDataSource,NewDao,NewService,NewController)
funcgetItemList(whttp.ResponseWriter,r*http.Request){
controller:=initializeController()
itemList,_:=controller.GetItemList()
output,_:=json.Marshal(itemList)
fmt.Fprintf(w,string(output))
funcmain(){
http.HandleFunc("/items",getItemList)
err:=http.ListenAndServe(":8080",nil)
iferr!=nil{
panic(err)
}
关键代码:
//执行wire命令前的代码
funcinitializeController()*Controller{
wire.Build(MegaSet)
returnController{}
//执行后生成的代码
//Injectorsfrommain.go:
funcinitializeController()*Controller{
dataSource:=NewDataSource()
dao:=NewDao(da
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026上海市信息安全测评认证中心招聘2人备考题库【典型题】附答案详解
- 2026海南海口市美兰区校园招聘教师45人备考题库(一)附完整答案详解【夺冠】
- 2026江苏盐城市滨海县校园招聘教师76人备考题库含答案详解【达标题】
- 2026云南临沧市耿马孟康中医医院招聘6人备考题库参考答案详解
- 2026云南白药集团春季校园招聘备考题库及答案详解【全优】
- 2026中国移动通信集团四川有限公司青神分公司招聘12人备考题库附答案详解【考试直接用】
- 2026广西柳州市鱼峰区洛埠镇卫生院招聘2人备考题库含完整答案详解(网校专用)
- 2026江苏镇江市卫生健康委员会所属镇江市第一人民医院招聘32人备考题库及参考答案详解【基础题】
- 2026云南玉溪易门县教育体育局招聘后勤辅助人员10人备考题库含完整答案详解(有一套)
- 2026湖北黄石市大冶市事业单位统一招聘118人备考题库【巩固】附答案详解
- (高清版)DG∕TJ 08-110-2021 餐饮单位清洁设计技术标准
- 年产200吨高纯金属铯铷项目报告书
- 煤矿各级各岗位人员职业病防治责任制
- (高清版)DB11∕T2370-2024生态修复树种选择技术规范
- 2025新人教版七年级下册英语 Unit 2知识点梳理及语法讲义(答案版)
- 见证取样送检计划方案
- (新版)多旋翼无人机超视距驾驶员执照参考试题(附答案)
- 2025年包钢(集团)公司招聘笔试参考题库含答案解析
- 【公开课】多姿与多彩(生活色彩)课件高中美术人教版+(2019)+选择性必修1+绘画
- 房产销售人员劳动合同范本专业版
- 《植物生产与环境》考试复习题及答案
评论
0/150
提交评论