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) // 删除
}
相关推荐
爱丫爱1 分钟前
Python中常见库 PyTorch和Pydantic 讲解
开发语言·pytorch·python
Ryan_Gosling2 分钟前
C++-构造函数-接口
开发语言·c++
服务端相声演员1 小时前
Oracle JDK、Open JDK zulu下载地址
java·开发语言
19岁开始学习1 小时前
Go学习-入门
开发语言·学习·golang
一小路一1 小时前
Go Web 开发基础:从入门到实战
服务器·前端·后端·面试·golang
青铜念诗1 小时前
python脚本文件设置进程优先级(在.py文件中实现)
开发语言·python
一念春风2 小时前
C# 背景 透明 抗锯齿 (效果完美)
开发语言·c#
Igallta_8136222 小时前
【小游戏】C++控制台版本俄罗斯轮盘赌
c语言·开发语言·c++·windows·游戏·游戏程序
Dyan_csdn2 小时前
【Python项目】文本相似度计算系统
开发语言·python
pianmian12 小时前
python绘图之回归拟合图
开发语言·python·回归