前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Go 语言中怎么使用依赖注入?

Go 语言中怎么使用依赖注入?

作者头像
frank.
发布于 2024-04-02 08:51:51
发布于 2024-04-02 08:51:51
17600
代码可运行
举报
运行总次数:0
代码可运行

01

介绍

在 Go 语言项目开发中,我们处理组件层级之间的依赖关系时,通常我们会先在依赖层级的代码中实例化被依赖层级,然后调用它的方法,即依赖方需要主动获取被依赖方。

但是,当被依赖层级的代码发生变化时,依赖层级的代码也需要修改,耦合性比较高,代码不方便扩展。

所谓依赖注入,即依赖方不再需要主动获取被依赖方,而是被依赖方主动传递给依赖方。

本文我们介绍 Go 语言怎么使用依赖注入。

02

Go 语言使用依赖注入

在 Go 语言中,怎么使用依赖注入呢?我准备以 clean arch 架构的代码讲解。

推荐读者朋友们先阅读我之前写的一遍文章 「Go 语言整洁架构实践」。

参照 Bob 大叔的一篇关于整洁架构的文章 The Clean Architecture,我们分 4 个层级:

  1. Models
  2. Repository
  3. Usecase
  4. Delivery

限于篇幅,本文主要介绍在 Go 语言中使用构造函数的方式实现依赖注入,读者朋友们可以在留言区分享其它实现方式。

示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Models 层
type Todolist struct {
 Id      int64  `json:"id"`
 Title   string `json:"title"`
 Status  int    `json:"status"`
 Created int    `json:"created"`
 Updated int    `json:"updated"`
}

type TodoListRepository interface {
 Create(ctx context.Context, t *Todolist) (err error)
}

type TodoListUsecase interface {
 Create(context.Context, *Todolist) (err error)
}

// Repository 层
type mysqlTodoListRepository struct {
 Conn *sql.DB
}

func NewMysqlTodoListRepository(Conn *sql.DB) models.TodoListRepository {
 return &mysqlTodoListRepository{Conn}
}

func (m *mysqlTodoListRepository) Create(ctx context.Context, t *models.Todolist) (err error) {
 // ...
 return
}

// Usecase 层
type todoListUsecase struct {
 todoListRepo models.TodoListRepository
}

func NewTodoListUsecase(t models.TodoListRepository) models.TodoListRepository {
 return &todoListUsecase{
  todoListRepo: t,
 }
}

func (tl *todoListUsecase) Create(ctx context.Context, t *models.Todolist) (err error) {
 if t.Title == "" {
  return fmt.Errorf("illegal parameter")
 }
 return tl.todoListRepo.Create(ctx, t)
}

// Delivery 层
type TodoListHandler struct {
 TodoListUsecase models.TodoListUsecase
}

func NewTodoListHandler(r *gin.Engine, todoListUsecase models.TodoListUsecase) {
 handler := &TodoListHandler{
  TodoListUsecase: todoListUsecase,
 }
 r.POST("/create", handler.Create)
 r.Run()
}

// main 函数
func main() {
 conn, err := sql.Open(`mysql`, "root:root@tcp(127.0.0.1:3306)/todolist")
 if err != nil {
  log.Fatal(err)
 }
 r := gin.Default()
 todoListRepository := mysql.NewMysqlTodoListRepository(conn)
 todoListUsecase := usecase.NewTodoListUsecase(todoListRepository)
 http.NewTodoListHandler(r, todoListUsecase)
}

阅读上面这段代码,我们可以发现 Repository 层依赖数据库驱动 conn,Usecase 层依赖 Repository 层,Delivery 层依赖 Usecase 层。

以 Repository 层和 Usecase 层为例,我们可以发现 Usecase 层通过构造函数 func NewTodoListUsecase(t models.TodoListRepository) models.TodoListRepository 将其依赖项 models.TodoListRepository 以参数的形式传递过来,并将其放入 todoListUsecase 结构体中。

所以,我们使用 Usecase 层的构造函数 NewTodoListUsecase 创建 Usecase 对象时,需要先使用 Repository 层的构造函数 NewMysqlTodoListRepository 创建 Repository 对象,并将其以参数的形式传递给 Usecase 层的构造函数 NewTodoListUsecase

通过依赖注入的方式,可以有效降低组件层级之间的耦合性,方便代码的扩展。比如示例代码中 Repository 层的方法修改代码,不会影响 Usecase 层的代码。

03

依赖注入工具

除了手写依赖注入代码,我们也可以使用依赖注入工具,开源社区有很多依赖注入工具,其中比较流行的主要有以下 3 个。

Google 开源的依赖注入工具 Wire[1],它是一个代码生成工具,也就是说它是在编译时自动生成代码。

另外 2 个依赖注入工具是在运行时基于 Go 反射实现,分别是 uber开源的依赖注入工具 Dig[2]facebook 开源的依赖注入工具[3]

读者朋友们可以根据实际开发中的需求,选择合适的工具。

04

总结

读者朋友们可能已经发现,依赖注入实际上就是面向对象五大原则之一,依赖倒置原则的实现方式。

我们可以在 Go 项目开发中,使用依赖注入的方式,降低组件层级之间的代码耦合性,使代码更方便扩展。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言开发栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Go 语言整洁架构实践
Bob 大叔在他的一篇标题为「整洁架构」的博客中提及,现在一些流行的系统架构,都采用软件分层设计,都主张以下 5 个规则:
frank.
2022/05/17
6520
从理论到实践:Go 项目中的整洁架构设计
你维护的 Go 项目代码架构是什么样子的?六边形架构?还是洋葱架构?亦或者是 DDD?无论项目采用的是什么架构,核心目标都应是一致的:使代码能够易于理解、测试和维护。
陈明勇
2024/12/06
4247
从理论到实践:Go 项目中的整洁架构设计
Go: 使用依赖注入实现Gin框架路由处理函数的解耦
在Go语言开发中,Gin是一个非常流行的Web框架。其轻量级、高性能的特点,使其成为许多开发者的首选。然而,在实际项目中,随着业务逻辑的复杂化,我们往往会遇到代码耦合严重、测试困难等问题。依赖注入(Dependency Injection, DI)是一种有效的解耦手段,能够帮助我们实现代码的高内聚、低耦合,从而提升代码的可维护性和可测试性。本文将探讨如何在Gin框架中使用依赖注入来解耦路由处理函数。
运维开发王义杰
2024/05/29
3890
Go: 使用依赖注入实现Gin框架路由处理函数的解耦
Golang 简洁架构实战
由于golang不像java一样有一个统一的编码模式,所以我们和其他团队一样,采用了 Go 面向包的设计和架构分层这篇文章介绍的一些理论,然后再结合以往的项目经验来进行分包:
luozhiyun
2022/05/09
1.2K0
Golang 简洁架构实战
Go 应用程序设计标准
众所周知 Go 语言官方成员 Russ Cox 曾向 Go 社区回应并没有 Go 应用程序设计标准。但是,为什么本文还要使用这个标题呢?
frank.
2022/05/17
2360
Go 项目必备:深入浅出 Wire 依赖注入工具
在日常项目开发中,我们经常会使用到依赖注入的设计模式,目的是为了降低代码组件之间的耦合度,提高代码的可维护性、可扩展性和可测试性。
陈明勇
2023/09/21
1.8K0
Go 项目必备:深入浅出 Wire 依赖注入工具
Go 语言微服务框架 Kratos 开发 HTTP API
本文我们分为开发环境,创建项目,代码目录,HTTP API,四个部分介绍 Kratos 微服务框架。
frank.
2024/12/23
3960
Go 语言微服务框架 Kratos 开发 HTTP API
Golang依赖注入提升开发效率!
导语 | 依赖注入并不是java独有的,也不是web框架独有的,本文用通俗易懂的语言讲解什么是依赖注入,为什么需要依赖注入,以及go语言如何使用依赖注入来提升开发效率。 一、什么依赖注入 依赖注入(Dependency Injection)也叫DI是软件工程的一种设计模式。 二、为什么需要依赖注入 比如我们使用go要开发一个http api服务,这个服务启动需要 读取命令行 读取配置 连接数据库 连接redis 设置回调函数 监听端口 这个服务关闭需要 关闭端口 关闭redis 关闭mysql 你的
腾讯云开发者
2022/08/26
1.2K0
Golang依赖注入提升开发效率!
我是如何组织 Go 代码的(目录结构 依赖注入 wire)
对于大多数 Gopher 来说,编写 Go 程序会直接在目录建立 main.go,xxx.go,yyy.go……
仁扬
2023/07/18
6390
uber-go/fx 源码分析
https://github.com/uber-go/fx是一个依赖注入框架,它是基于依赖注入库dig实现的(参考:dig 源码分析)。它简化了依赖注入,消除了全局状态的维护和 func init()。首先看下如何使用:
golangLeetcode
2022/12/17
8910
Go 每日一库之 sqlc
在 Go 语言中编写数据库操作代码真的非常痛苦!database/sql标准库提供的都是比较底层的接口。我们需要编写大量重复的代码。大量的模板代码不仅写起来烦,而且还容易出错。有时候字段类型修改了一下,可能就需要改动很多地方;添加了一个新字段,之前使用select *查询语句的地方都要修改。如果有些地方有遗漏,可能就会造成运行时panic。即使使用 ORM 库,这些问题也不能完全解决!这时候,sqlc来了!sqlc可以根据我们编写的 SQL 语句生成类型安全的、地道的 Go 接口代码,我们要做的只是调用这些方法。
用户7731323
2020/09/08
2.7K0
YoyoGo微服务框架入门系列-快速编写WEB API
YoyoGo是一个使用Golang编写的一个简单、轻量、快速、基于依赖注入的微服务框架,目前依然在研发阶段,欢迎Star以及一起参与到框架的研发
yoyofx
2020/12/08
6310
golang源码分析:dtm分布式事务(2)
在分析了qs的大致源码后golang源码分析:dtm分布式事务(1),我们分析下dtm-example的源码结构,每个例子都是类似的。
golangLeetcode
2023/03/01
4690
golang源码分析:dtm分布式事务(2)
Go 官方依赖注入工具wire
wire是Go官方推出的一款类似于Spring依赖注入工具。有别于以往的依赖注入工具facebookgo/inject、uber-go/dig等,采用反射实现。wire采用通过代码描述对象之间的依赖关系,然后自动生成代码在编译期实现依赖注入的工具 源码:https://github.com/google/wire
孤烟
2023/01/06
1.9K0
Go 项目依赖注入wire工具最佳实践介绍与使用
在Go语言的项目开发中,为了提高代码的可测试性和可维护性,我们通常会采用依赖注入(Dependency Injection,简称DI)的设计模式。依赖注入可以让高层模块不依赖底层模块的具体实现,而是通过抽象来互相依赖,从而使得模块之间的耦合度降低,系统的灵活性和可扩展性增强。
贾维斯Echo
2024/04/08
4230
Go 项目依赖注入wire工具最佳实践介绍与使用
go使用消息队列优化接口
在我们编写后端接口时,通常有些接口对于实时性的要求并不是那么高,但其中有些函数却相当占用接口调用时间,如调用第三方接口、发送短信、发送邮件等等。为了提升用户的体验感、系统的稳定性,此时我们就可以使用消息队列对于接口进行优化,对于实时性要求不高的接口使用消息队列来进行处理,提高api响应速度,优化用户体验。本文将以go语言使用rabbitMQ来演示如何对于一个接口进行优化。
陈杪秋
2024/07/22
1140
Go 语言错误处理为什么更推荐使用 pkg/errors 三方库?
Go 语言项目开发中,我们通常需要在代码逻辑中进行错误处理,Go 官方标准库 errors 为我们提供了一些方法,比如 New,Unwarp,Is 和 As。
frank.
2022/07/01
8870
聊聊go-bank-transfer项目对Clean Architecture的实践
本文主要赏析一下go-bank-transfer对于 Clean Architecture的实践
code4it
2021/03/21
4420
聊聊go-bank-transfer项目对Clean Architecture的实践
Jetpack新成员,一篇文章带你玩转Hilt和依赖注入
虽然今年的Google I/O大会由于疫情的原因没能开成,但是Google每年要发布的各种新技术可一样都没少。
用户1158055
2020/11/26
2.7K0
Jetpack新成员,一篇文章带你玩转Hilt和依赖注入
Go 单元测试之Mysql数据库集成测试
sqlmock 是一个用于测试数据库交互的 Go 模拟库。它可以模拟 SQL 查询、插入、更新等操作,并且可以验证 SQL 语句的执行情况,非常适合用于单元测试中。
贾维斯Echo
2024/04/18
2380
Go 单元测试之Mysql数据库集成测试
相关推荐
Go 语言整洁架构实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验