PS: 若不了解控制反转和依赖注入,可参考博文:控制反转 IoC 与依赖注入 DI
简介
wire 库是管理和解析依赖关系的。
随着项目规模的增长,手动管理依赖关系变得越来越困难,容易导致代码的复杂性和耦合度增加。为了解决这一问题,Google 开发了一个名为 wire 的依赖注入工具,它可以自动生成依赖注入代码,帮助开发者管理依赖关系,提高代码的清晰度和可维护性。
GitHub 地址:https://github.com/google/wire
安装命令
go install github.com/google/wire/cmd/wire@latest
命令使用
在定义的 wire.go 文件所在目录执行 wire 命令即可生成 wire_gen.go 文件
场景示例
以常见的 controller、service、model 模式的依赖注入为例,以下示例为基于 gin 框架的实现:
控制层 userController.go
package controller
// 省略 import
type UserController struct {
// 注入服务层
UserService *service.UserService
}
// NewUserController UserController 构造器
// 交给 wire 注入
func NewUserController(userService *service.UserService) *UserController {
return &UserController{UserService: userService}
}
func (uC *UserController) GetAllUser(c *gin.Context) {
//
var body dto.UsersFilterDTO
if err := c.ShouldBindJSON(&body); err != nil {
response.Failed(c, response.ParamsError)
return
}
// 调用服务层
data := uC.UserService.GetAllUser(c, body)
//
response.SuccessWithData(c, data)
}
服务层 userService.go
package service
// 省略 import
type UserService struct {
UserModel *entity.UserModel // 注入模型类
// RedisService *RedisService // 注入 Redis 服务
}
// NewUserService UserService 构造器
// 交给 wire 注入
func NewUserService(userModel *entity.UserModel) *UserService {
return &UserService{UserModel: userModel}
}
func (uS *UserService) GetAllUser(c *gin.Context, body dto.UsersFilterDTO) []vo.UserDetailInfo {
var users []vo.UserDetailInfo
if err := db.Model(uS.UserModel).Where(body).Find(&users).Error; err != nil {
log.Printf("query users err:%v", err)
panic(err)
}
return users
}
wire.go
此文件不会被编译识别,通过在当前文件夹下执行 wire 命令从而生成 wire_gen.go 文件,生成的 InitializeApp 方法被 route.go 中调用
//go:build wireinject
// +build wireinject
package wire
// 省略 import
// 在本文件所在目录下执行 wire 命令
var UserSet = wire.NewSet(
controller.NewUserController,
service.NewUserService,
entity.NewUserModel,
)
var DemoSet = wire.NewSet(
controller.NewDemoController,
service.NewDemoService,
// rabbitMQ.NewRabbitMQService,
)
// AppSet 包含了所有模型的 ProviderSet
var AppSet = wire.NewSet(
UserSet,
DemoSet,
// 可以在这里继续添加其他模块的 ProviderSet
)
type AppControllers struct {
UserController *controller.UserController
DemoController *controller.DemoController
}
// InitializeApp 初始化整个应用的控制器, 返回全局应用的 AppControllers
func InitializeApp() (*AppControllers, error) {
wire.Build(AppSet, wire.Struct(new(AppControllers), "*"))
return &AppControllers{}, nil
}
route.go
gin 中的路由注册。通过 wire_gen.go 中生成的 InitializeApp 方法获取控制器
appController, _ := wire.InitializeApp()
userGroup := apiGroup.Group("user")
{
userGroup.POST("info/all", appController.UserController.GetAllUser)
}