当前位置: 首页 > article >正文

Go语言依赖注入方式

在Go语言中,依赖注入(Dependency Injection,DI)是一种设计模式,允许你将对象的依赖关系在外部进行管理,而不是让对象自己创建或查找依赖。通俗来说就是把一个对象所需要的东西如方法或属性(统称依赖)从外面传递给它,而不是让这个对象自己去找或实现这些东西。这种模式可以帮助你构建更可维护、可测试的代码。Go语言本身没有像一些面向对象语言(如Java)那样内置的依赖注入框架,但你可以通过多种方式实现依赖注入。

一、构造函数注入

构造函数注入是最常见的依赖注入方式之一。你可以在对象的构造函数中通过参数传递依赖。

package main

import "fmt"

// 定义依赖接口
type Service interface {
    Serve() string
}

// 实现接口的具体类型
type MyService struct{}

func (s MyService) Serve() string {
    return "MyService is serving"
}

// 使用依赖的结构体
type Controller struct {
    service Service
}

// 构造函数,注入依赖
func NewController(s Service) *Controller {
    return &Controller{service: s}
}

// 封装控制器的方法调用依赖
// 外部不需要直接访问 service 字段。这是一种良好的编程实践,它隐藏了内部实现细节,保证了接口的最小暴露。
// 使用依赖注入的核心目的之一是解耦和灵活性。如果你在外部代码中直接访问 controller.service.Serve(),你实际上绕过了依赖注入的封装,HandleRequest 方法可以让你的代码更容易进行单元测试
// 灵活性。HandleRequest 可以对 Serve() 的调用进行一些额外的操作。将来如果你希望在调用 Serve() 之前或之后做一些其他处理,比如日志记录、权限检查、错误处理等,封装一个方法会更加方便
func (c *Controller) HandleRequest() {
    fmt.Println(c.service.Serve())
}

func main() {
    // service实现了Service接口,把service通过NewController构造函数注入到controller中
    service := MyService{}
    controller := NewController(service)
    controller.HandleRequest()
}

二、接口注入

你可以使用接口将依赖注入,这样可以更灵活地替换实现。

package main

import "fmt"

// 定义依赖接口
type Service interface {
    Serve() string
}

type MyService struct{}

func (s MyService) Serve() string {
    return "MyService is serving"
}

// Controller依赖于Service接口
// 结构体嵌入接口,嵌入是Go语言的一种特性,允许你将一个类型嵌入到另一个类型中,使其拥有嵌入类型的所有方法。
type Controller struct {
    Service
}

func main() {
    service := MyService{}
    // Controller嵌入了Service接口,意味着Controller结构体需要提供一个Service接口实现,即service
    controller := Controller{service}
    fmt.Println(controller.Serve())
    // 不建议fmt.Println(controller.Service.Serve())调用
    // Controller 嵌入了 Service 接口,嵌入结构体的所有方法会提升到外部结构体中
    // controller.Serve()这样代码更简洁、易读,符合Go语言的惯用方式
    // 有方法名冲突或出于调试目的可以controller.Service.Serve()调用
}

三、Setter注入

package main

import "fmt"

type Service interface {
    Serve() string
}

type MyService struct{}

func (s MyService) Serve() string {
    return "MyService is serving"
}

type Controller struct {
    service Service
}

// Setter 方法用于注入依赖
func (c *Controller) SetService(s Service) {
    c.service = s
}

func (c *Controller) HandleRequest() {
    fmt.Println(c.service.Serve())
}

func main() {
    service := MyService{}
    controller := Controller{}
    controller.SetService(service)
    controller.HandleRequest()
}

四、Google的Wire库

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

使用 wire 生成依赖代码,基本步骤如下:

// wire_example.go
package main

import (
    "fmt"
    "github.com/google/wire"
)

// 定义Service
type Service interface {
    Serve() string
}

type MyService struct{}

func (s MyService) Serve() string {
    return "MyService is serving"
}

// Controller依赖Service
type Controller struct {
    service Service
}

// 构造函数
func NewMyService() Service {
    return &MyService{}
}

func NewController(s Service) *Controller {
    return &Controller{service: s}
}

// 使用wire生成依赖
func InitializeController() *Controller {
    wire.Build(NewMyService, NewController)
    return &Controller{}
}

func main() {
    controller := InitializeController()
    fmt.Println(controller.service.Serve())
}

运行 wire 命令后,wire.go 文件会生成代码,管理你的依赖。

wire


http://www.kler.cn/news/360339.html

相关文章:

  • 高效容器化技术(2)---docker的安装
  • 实用好助手
  • 【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (一):项目简介及安装依赖
  • SpringBoot和Vue的图片上传的解决方案
  • Java爬虫API:获取商品详情数据的利器
  • 基于SpringBoot+Vue+uniapp微信小程序的教学质量评价系统的详细设计和实现
  • 构建可扩展、安全和智能的数字化解决方案:微服务架构与物联网的深度融合
  • gitlab项目转移群组
  • 汇编实现逆序复制数据
  • 物联网防爆气象站的工作原理
  • C07.L10.STL之队列
  • 【推导过程】常用离散分布的数学期望、方差、特征函数
  • 物流行业创新:SpringBoot技术应用
  • 明日周刊-第23期
  • AI赋能大尺度空间模拟与不确定性分析及数字制图
  • docker compose部署mongodb 分片集群
  • 新版idea菜单栏展开与合并
  • 机器视觉基础系列四—简单了解背景建模算法
  • AI 通俗解读统计学和机器学习的主要区别
  • [AWS]RDS数据库版本升级