首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >手把手,带你从零封装Gin框架(十二):使用 Wire 依赖注入重构

手把手,带你从零封装Gin框架(十二):使用 Wire 依赖注入重构

作者头像
用户10002156
发布于 2024-01-23 15:56:38
发布于 2024-01-23 15:56:38
1.6K0
举报
文章被收录于专栏:生活处处有BUG生活处处有BUG

前言

由于之前项目中各个组件都是通过全局变量传递的,随着项目的推进,一大堆全局变量会混成一团,如果一不小心在某个地方对全局变量进行修改将可能引发严重的 panic,便打算使用依赖注入重构一下, Wire 是一个灵活的依赖注入工具,能够帮助我们在程序编译期就完成依赖注入。

依赖注入简述

依赖注入是指组件在创建时,就应该获取该组件所依赖的其他关系,如下代码所示,要创建一个 App 实例需要 Config 、 Server 结构体,分别展示使用与未使用依赖注入的两种方式。

代码语言:javascript
复制
type App struct {
    conf *Config
    httpServer *Server
}

// 构建 Config
func InitConfig() *Config {
    return &Config{}
}

// 构建 Server
func NewHttpServer() *Server {
    return &Server{}
}

// 构建 App (内部调用依赖组件的构建函数)
func NewApp() *App {
    return &App{
        conf: InitConfig(),
        httpServer: NewHttpServer(),
    }
}

// 构建 App (需由调用者传入依赖组件)
func NewAppByDI(conf *Config, httpSrv *Server) *App {
    return &App{
        conf: conf,
        httpServer: httpSrv,
    }
}

func main() {
    // 未使用依赖注入
    app := NewApp()
  
    // 使用依赖注入
    config := InitConfig()
    server := NewHttpServer()
    app := NewAppByDI(config, server)
}
  • • 未使用依赖注入的情况下,调用者无法知道 App 内部使用了 Config 和 Server ,如果 Config 构建函数 InitConfig() 发生变化,假设需要增加一个参数,我们就需要在每个调用 InitConfig() 的地方修改代码。
  • • 使用依赖注入的情况下,将 Config 和 Server 的构建逻辑与构建 App 的逻辑分离开,即使 Config 的构建函数 InitConfig 发生了变化,也只需要修改一处代码,但是在构建 App 之前,需要手动构建 Config 和 Server ,随着程序推进,这些依赖关系将越来越复杂,这时候就需要依赖注入工具 Wire 来帮助我们生成依赖关系。

安装工具

代码语言:javascript
复制
# 导入项目
go get -u github.com/google/wire

# 安装命令
go install github.com/google/wire/cmd/wire

工作原理简述

Wire 有两个核心概念 Provider 和 Injector 。

Provider 就是各组件的构建函数,这些函数需要接收依赖的组件为参数,创建组件并返回,就是上面例子中的 NewAppByDI() 函数。

Injector 是由 Wire 自动生成的函数,它会根据依赖的顺序调用 Provider,为了生成该函数,通常在 wire.go 文件中定义 Injector 函数签名,在其函数内部调用 wire.Build() ,并以所需 Provider 作为参数(无须考虑顺序)。

重构

这里只简单展示一下 wire.go 文件,主要工作就是先为之前项目中使用的各个组件都编写 Provider 函数,然后在 wire.Build() 中传入各个 Provider 即可,完整代码请查看 https://github.com/jassue/jassue-gin/tree/main。

代码语言:javascript
复制
//go:build wireinject
// +build wireinject

package main

import (
    "github.com/google/wire"
    "github.com/jassue/gin-wire/app/compo"
    "github.com/jassue/gin-wire/app/cron"
    "github.com/jassue/gin-wire/app/data"
    "github.com/jassue/gin-wire/app/handler"
    "github.com/jassue/gin-wire/app/service"
    "github.com/jassue/gin-wire/config"
    "github.com/jassue/gin-wire/router"
    "go.uber.org/zap"
    "gopkg.in/natefinch/lumberjack.v2"
)

// wireApp init application.
func wireApp(*config.Configuration, *lumberjack.Logger, *zap.Logger) (*App, func(), error) {
    panic(wire.Build(data.ProviderSet, compo.ProviderSet, service.ProviderSet, handler.ProviderSet, router.ProviderSet, cron.ProviderSet, newHttpServer, newApp))
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 前言
  • 依赖注入简述
  • 安装工具
  • 工作原理简述
  • 重构
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档