Go新项目-Gin中wire的依赖注入方式实战(6)

选型Go项目过程中,针对依赖注入方式的分析和使用

参考资料

wire与其他同类工具的对比

Wire 是一个轻巧的Golang依赖注入工具。它由Go Cloud团队开发,通过自动生成代码的方式在编译期完成依赖注入。

依赖注入是保持软件 "低耦合、易维护" 的重要设计准则之一

同类型哦工具有:来自Uber 的 dig 、来自Facebook 的 inject,下边我们只对比下wire和dig

wire和dig的区别

uber 推出的依赖注入库,采用反射,在运行时计算依赖关系,构造依赖对象。

上面简单介绍了wire 和 dig 两者之间的特点:

1、dig 通过反射识别依赖关系,wire 是编译前计算依赖关系

2、dig 只能在代码运行时,才能知道哪个依赖不对,比如构造函数返回类型的是结构体指针,但是其他依赖的是interface,这样的错误只能在运行时发现,而wire可以在编译的时候就发现。

3、由于采用了依赖注入,所以在代码调试时可以注入一些mock 服务或者函数,wire在mock上支持更友好些,dig的话可以通过build tag 来使用mock。 个人比较推荐使用wire,可以在编译时就发现问题,避免了 多次的build和尝试后才解决编译问题。更多的使用方式和最佳实践,可以参考官方文档。

根据依赖倒置原则(Dependence Inversion Principle),对象应当依赖于接口,而不是直接依赖于具体实现。

使用wire的优势:

  • 方便debug,若有依赖缺失编译时会报错
  • 因为不需要 Service Locators, 所以对命名没有特殊要求
  • 避免依赖膨胀。生成的代码只包含被依赖的代码,而运行时依赖注入则无法作- 到这一点
  • 依赖关系静态存于源码之中, 便于工具分析与可视化

wire 中的两个核心概念: Provider 和 Injector

provider: a function that can produce a value. These functions are ordinary Go code.

injector: a function that calls providers in dependency order. With Wire, you write the injector's signature, then Wire generates the function's body.

  • Provider 是一个生成组件的普通函数,这个函数会返回构建依赖关系所需的组件。
  • Injector 是很多个 Provider 组装在一起的时候,可以得到一个管理对象,由wire自动生成的函数。函数内部会按根据依赖顺序调用相关privoder 。

使用wire实战

安装

用法效果对比

wire 依赖注入方式想要达到的效果:

我们有一个主函数:

func main() {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)

event.Start()
}

我们改成这样:

func main() {
event := InitializeEvent()
event.Start()
}

代码目录结构

├── routes
│   ├── init_server.go
│   ├── routes.go
│   ├── wire.go
│   └── wire_gen.go

第一步:编写wire.go

//go:build wireinject
// +build wireinject

package routes


import (
"gdonline_backend/databases/redis"
"github.com/google/wire"
"github.com/rs/zerolog"
"gorm.io/gorm"

"gdonline_backend/internal/controller"
"gdonline_backend/internal/dao"
"gdonline_backend/internal/service"
)

var chpoPhenotype = wire.NewSet(
dao.NewChpoPhenotypeDao,
wire.Bind(new(dao.IChpoPhenotypesDao), new(*dao.ChpoPhenotypesDao)),
service.NewChpoPhenotypeService,
controller.NewChpoPhenotypesController,
)

func InitChpoPhenotypes(db *gorm.DB, log *zerolog.Logger) *controller.ChpoPhenotypesController {
panic(wire.Build(chpoPhenotype))
}

第二步:wire

第三步:生成 wire_gen.go

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package routes

import (
"gdonline_backend/databases/redis"
"gdonline_backend/internal/controller"
"gdonline_backend/internal/dao"
"gdonline_backend/internal/service"
"github.com/google/wire"
"github.com/rs/zerolog"
"gorm.io/gorm"
)

// Injectors from wire.go:

func InitChpoPhenotypes(db *gorm.DB, log *zerolog.Logger) *controller.ChpoPhenotypesController {
chpoPhenotypesDao := dao.NewChpoPhenotypeDao(db, log)
chpoPhenotypesService := service.NewChpoPhenotypeService(chpoPhenotypesDao)
chpoPhenotypesController := controller.NewChpoPhenotypesController(chpoPhenotypesService)
return chpoPhenotypesController
}

// wire.go:

var chpoPhenotype = wire.NewSet(dao.NewChpoPhenotypeDao, wire.Bind(new(dao.IChpoPhenotypesDao), new(*dao.ChpoPhenotypesDao)), service.NewChpoPhenotypeService, controller.NewChpoPhenotypesController)

第四步:main.go 中调用

# routes>init_server.go

func InitServer() {
// 初始化数据库连接
db := mysql.DB
redisDB := redis.DB
zeroLog := logging.NewZerolog("business")

// 注册服务-wire
cc = InitChpoPhenotypes(db, zeroLog)

}

# main.go
routes.InitServer()

第五步:实际调用的路由

func Routes(r *gin.Engine) {
// 设置路由组: v1
v1 := r.Group("v1")
chpoPhenotype := v1.Group("chpo_phenotypes")
// 知识库管理
chpoPhenotype.GET("lists", cc.Lists)    // 列表接口
chpoPhenotype.GET("detail", cc.Detail)  // 获取表型详情
chpoPhenotype.POST("add", cc.Add)       // 新增
chpoPhenotype.POST("edit", cc.Edit)     // 编辑
chpoPhenotype.POST("delete", cc.Delete) // 删除
}
相关推荐
通信仿真实验室22 分钟前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&25 分钟前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
吾爱星辰4 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer4 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良4 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
Kalika0-05 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
代码雕刻家5 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
一个闪现必杀技5 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm
Fan_web5 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery