Go使用wire依赖注入工具

Go项目使用Wire依赖注入

概述

Wire 是一个由 Google 开源的依赖注入框架,它可以帮助你在 Go 项目中实现依赖注入。通过代码生成,Wire 在编译时连接组件,避免了运行时反射,使代码更易于理解和调试。那么什么是依赖注入?依赖了什么又注入了啥?
依赖注入(Dependency Injection,简称DI)是一种设计模式,在Java语言中用于去除类之间的依赖关系、实现松耦合,以便于开发和测试。这里的依赖指的是代码中某个对象或实例所依赖外部的某个对象或实例,所以这里的注入指的是被依赖的模块里。

要出大问题的写法

最开始写的项目初始化是这样子的,就以初始化Mysql为例,在初始化时通过全局变量传递依赖实例

Go使用wire依赖注入工具

Go使用wire依赖注入工具

Go使用wire依赖注入工具

 db这个对象游离在全局作用域,暴露给包下的其他模块比较危险。首先是会增加代码之间的耦合度,多个文件直接使用这些全局变量会使得项目难以维护和理解;然后是难以追踪,全局变量的修改和使用分散在不同的文件中,导致难以追踪和理解代码的行为;最后是并发问题,全局变量在并发环境中容易引起竞态条件,多个协程同时访问和修改全局变量可能会导致数据不一致或其他问题
所以我们使用依赖注入的方式来启动项目。

项目改进

修改读取配置文件代码(Mysql)

func InitMysqlConf() (mysqlconf *Mysql) {
    viper.SetConfigFile("./internal/config/config.yaml")
    if err := viper.ReadInConfig(); err != nil {
        panic(fmt.Errorf("Read Config failed err %v", err))
    }
    var appconf AppConfig
    if err := viper.Unmarshal(&appconf); err != nil {
        panic(fmt.Errorf("unmarshal to Conf failed ,err %v", err))
    }
    mysqlconf = appconf.Mysql
    log.Println("load config file success!", mysqlconf)
    return mysqlconf
}

修改初始化Mysql

func InitDB(conf *setting.Mysql) (db *gorm.DB) {
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", conf.User, conf.Password, conf.Host, conf.Port, conf.DB)
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }
    log.Println("Mysql init success")
    return db
}

修改DAO层

type UserDao struct {
    db *gorm.DB
}

// 创建一个userDAO实例
func NewUserDao(db *gorm.DB) *UserDao {
    return &UserDao{db: db}
}

修改logic层

type UserLogic struct {
    userDao *dao.UserDao
}

func NewUserLogic(userDao *dao.UserDao) *UserLogic {
    return &UserLogic{userDao: userDao}
}

修改controller层

type UserController struct {
    userLogic *logic.UserLogic
}

func NewUserController(userLogic *logic.UserLogic) *UserController {
    return &UserController{userLogic: userLogic}
}

在main函数初始化

func main() {
    conf := setting.InitConf()
    db := dao.InitDB(conf.Mysql)
    userDao := dao.NewUserDao(db)
    userLogic := logic.NewUserLogic(userDao)
    userController := controller.NewUserController(userLogic)
    ....
    router := gin.Default()
  ...
}

是时候使用wire了

 wire 是一个轻量级的 Go 语言依赖注入代码生成工具。它由 Google 开源,用于在编译期自动生成依赖注入相关的代码。与其他需要运行时反射的依赖注入工具不同,wire 能够在编译期检测依赖关系,确保更好的性能和可靠性。
上面我们通过手工注入依赖,问题在于如果未来要维护的东西多了,人工输入多层次的一堆依赖非常麻烦;而wire能自动帮你注入依赖。那要怎么做呢?首先wire里有两个基本概念,分别是injectorproviderprovider就是上面初始化时的普通Go函数,injector就负责传入各种组件的初始化方法。话不多说我们来看看怎么实现。

下载wire

go install github.com/google/wire/cmd/wire@latest 

定义injector

我们需要新建一个wire.go的文件,要记得写入//go:build wireinject,它的作用是告诉wire工具在这个文件中执行代码生成,当运行wire时,它会根据这个注释生成相应的依赖注入代码;初始化的方法顺序可以随便写,wire都能够分析出来。
//go:build wireinject

package wire

import (
    "github.com/google/wire"
    "wiretes/internal/controller"
    "wiretes/internal/dao"
    "wiretes/internal/logic"
    "wiretes/internal/setting"
)

func InitializeApp() (*controller.UserController, error) {
    // 传入各种组件的初始化方法
    wire.Build(
       setting.InitMysqlConf, // 读取mysql配置
       dao.InitDB, // 新建mysql实例
       controller.NewUserController, // 新建usercontroller实例
       logic.NewUserLogic, // 新建userlogic实例
       dao.NewUserDao) // 新建userdao实例

    return &controller.UserController{}, nil
}

wire生成依赖注入代码

运行wire gen 指令,此时wire工具会根据wire.go文件中定义的依赖关系生成代码,生成一个名为wire_gen.go的文件,看到生成的内容就是我们刚才自己手工输入的依赖注入的代码。
❯ wire gen                                                                                   
wire: wiretes/internal/wire: wrote /Users/hezefeng/GolandProjects/wiretest/internal/wire/wire_gen.go

Go使用wire依赖注入工具

修改main函数再测试一下

由于刚才在injector那定义返回了一个userController,所以我们在main函数拿出来就能用。
func main() {
    userController, err := wire.InitializeApp()
    if err != nil {
        panic("wire Initialize App error")
    }

    router := gin.Default()
    router.POST("/user", userController.CreateUser)

    err = router.Run(":8555")
    if err != nil {
        return
    }
}

Go使用wire依赖注入工具

写在最后

本人是新手小白,如果这篇笔记中有任何错误或不准确之处,真诚地希望各位读者能够给予批评和指正。谢谢!练习的代码放在这里–↓
https://github.com/FengZeHe/LearnGolang/tree/main/project/WireDemo


原文始发于微信公众号(ProgrammerHe):Go使用wire依赖注入工具

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/239085.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!