Go语言依赖注入方式

devtools/2024/10/21 11:56:17/

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

一、构造函数注入

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

package mainimport "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 mainimport "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接口实现,即servicecontroller := Controller{service}fmt.Println(controller.Serve())// 不建议fmt.Println(controller.Service.Serve())调用// Controller 嵌入了 Service 接口,嵌入结构体的所有方法会提升到外部结构体中// controller.Serve()这样代码更简洁、易读,符合Go语言的惯用方式// 有方法名冲突或出于调试目的可以controller.Service.Serve()调用
}

三、Setter注入

package mainimport "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 mainimport ("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.ppmy.cn/devtools/127555.html

相关文章

Oracle10g运维 表增删改查

增两条数据,查一条数据,改一条数据,删除一条数据 INSERT INTO T_OWNERTYPE (ID,NAME) VALUES (1,居民); COMMIT; INSERT INTO T_OWNERS VALUES (1,张三,1,123,123,SYSDATE,1); COMMIT;SELECT * FROM T_OWNERS;UPDATE T_OWNERS SET NAME里斯…

《Vue3 版本差异》Vue3.5+ 在组件或HTML元素绑定 ref 差异

组件上的 ref,组合式写法的变化; 在 2024.09.03 发布的 v3.5.0 版上新增接口 useTemplateRef; v3.5 之前 代码第 8 行,导入 ref;代码第 10 行,使用 ref 传参为 null,变量名与 第三行 ref 同…

滚雪球学Redis[8.1讲]:Redis插件与扩展模块:模块化架构的强大扩展能力

全文目录: 🎉前言🚦1. Redis Modules概述🎯1.1 什么是Redis模块?🪀1.2 Redis模块的核心功能 ⚙️2. 常用Redis模块介绍与使用🏓2.1 RedisSearch🏸2.2 RedisJSON🎳2.3 Red…

jmeter中对于有中文内容的csv文件怎么保存

jmeter的功能很强大,但是细节处没把握好就得不到预期的结果。今天来讲讲有中文内容的csv文件的参数化使用中需要注意的事项。 对于有中文内容,涉及到编码格式,为了让jmeter能正确地读取csv文件中的中文,需要把文件转码为UTF-8BOM…

【AWS AMI跨境备份】跨境使用 S3 备份和还原 AMI 镜像

文章目录 一、实验场景二、实验目标三、实验架构图四、涉及到AWS服务五、演示操作5.1 创建EC2实例5.2 创建映像5.3 备份AMI至Global S35.4 复制AMI从Global S3至 CN S35.5 还原AMI5.6 测试AMI 六、参考链接 一、实验场景 将 AWS Global区域的EC2实例备份至 AWS CN区域。 备份…

【存储设备专栏 2.8 -- linux 下挂载命令 mount 与 gio mount】

> 请阅读【嵌入式及芯片开发学必备专栏】< 文章目录 mount 命令步骤卸载&#xff08;可选&#xff09; gio mountgio mount -d 详细介绍用法示例示例 1: 挂载 U 盘示例 2: 查看挂载的设备示例 3: 卸载设备 注意事项总结 mount 命令 要将插入到 Linux 系统的 U 盘&#x…

Ascend C算子编程和C++基础 Lesson3-2 矩阵编程

一、矩阵乘基础知识 二、矩阵乘的核函数 三、矩阵乘的Tiling

计算机网络基本架构示例2

一、企业内部网络架构 在一个中型企业中&#xff0c;通常会有以下的网络架构&#xff1a; - 核心层&#xff1a;由高性能的核心交换机组成&#xff0c;负责快速转发大量数据。例如采用具有高带宽和冗余功能的三层交换机&#xff0c;确保整个网络的稳定运行。它连接着各个部门的…