首页 > 其他分享 >Go 语言中怎么使用依赖注入

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

时间:2024-04-01 09:03:17浏览次数:26  
标签:依赖 models 代码 Usecase Go 注入

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

原创 frank Golang语言开发栈 2024-03-31 23:01 北京 听全文

大家好,我是 frank。
欢迎大家点击标题下方蓝色文字「Golang 语言开发栈」关注公众号。
公众号主页点击右上角三个点图标,
设为星标,第一时间接收推送文章。
文末扫码,加群一起学 Golang 语言。

01 

介绍

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

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

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

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

02 

Go 语言使用依赖注入

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

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

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

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

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

示例代码:

// 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 项目开发中,使用依赖注入的方式,降低组件层级之间的代码耦合性,使代码更方便扩展。

推荐阅读

  1. Go 1.22 对 net/http.ServeMux 多路复用器新增两个增强功能
  2. Prometheus Go client library 详解
  3. Go 语言使用标准库 sync 包的 mutex 互斥锁解决数据竞态
  4. GORM V2 安装和连接 MySQL
  5. Go 语言开源项目使用的函数选项模式
参考资料[1]

Google 开源的依赖注入工具 Wire: https://github.com/google/wire

[2]

uber开源的依赖注入工具 Dig: https://github.com/uber-go/dig

[3]

facebook 开源的依赖注入工具: https://github.com/facebookarchive/inject

 

图片

扫描二维码或回复「微信群」,加入微信群

图片

点「赞」和「在看」是最大的支持

标签:依赖,models,代码,Usecase,Go,注入
From: https://www.cnblogs.com/cheyunhua/p/18107682

相关文章

  • 如何开启Google Ads增强型转化?
    一.概述    GoogleAds向全量商家开放增强型转化功能,该功能将通过加密处理(SHA256方法)的第一方转化数据发送到Google,从而对现有的转化跟踪代码形成补充,旨在提高转化衡量准确性,提升优化效果。二.配置指南登录您的 GoogleAds帐号。点击帐号右上角的“工具和设置......
  • 学习日记之《Django3 Web应用开发实战》
    学习日记之《Django3Web应用开发实战》第二章——Django配置信息1、静态资源和媒体资源2、模板配置3、数据库配置4、中间件介绍第三章——初探路由1、反向解析2、重定向第四章——探究FBV视图1、异常响应2、文件下载功能3、文件上传功能自定......
  • Django的问题来这里看看看吧
    Django的问题来这里看看看吧1、django在centos7中报sqlite3版本错误解决2、django修改后台的名称及应用名称3、Django--Restframework--coreapi版文档BUG:AssertionError:`coreapi`mustbeinstalledforschemasupport.4、Django--drf-yasg版文档5、Djang......
  • 数据库之迁移常规操作(Mongodb篇)
    一、部署mongodb数据库。注:采用docker容器进行安装部署详情参考此文》》https://blog.csdn.net/u014642921/article/details/136022683二、在admin用户创建testdb文档插入两条数据admin>db.testdb.insertMany([{name:"1",age:1,addr:"earth"},{name:"2",age:2,addr:"......
  • SQL注入攻击与防御详细讲解
    一、SQL注入攻击1.利用单引号绕过过滤        许多应用程序使用单引号来包裹用户输入,以防止SQL注入攻击。然而,攻击者可以通过输入'OR1=1;--来绕过这种过滤。示例:        假设应用程序使用以下代码查询数据库:SELECT*FROMusersWHEREusername='......
  • IDEA中使用maven打包且包含依赖
    具体配置这里我们说的都是非SpringBoot项目正常我们在使用maven时,是不需要将依赖也包含进去的,但是如果想jar包能直接通过java-jar来执行,那么就需要包含依赖。<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artif......
  • Django路由
    Router介绍在实际开发过程中,一个Django项目会包含很多的app,这时候如果我们只在主路由里进行配置就会显得杂乱无章,所以通常会在每个app里,创建各自的urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的us.py模块中。而这个从主路由转发到各个应用路由的过......
  • Django学习_Day 1
    Day1学习笔记:学习视频:https://www.youtube.com/watch?v=yD0_1DPmfKM&list=PLQVvvaa0QuDe9nqlirjacLkBYdgc2inh37:30cmd命令'django-admin'管理命令来查看有什么命令可以运行'ThewayDjangoworksisassumesallwebsitesareactuallyjustacollectionofapps.'......
  • 在Go语言中如何避免接口污染
            在设计和构造代码时,接口是Go语言的基石之一。然而,就像许多工具或概念一样,滥用它们通常不是一个好主意。接口污染就是用不必要的抽象使我们的代码变得难以理解。这是来自另一种编程语言具有不同习惯的开发人员经常犯的错误。在深入讨论这个话题之前,让我们重新思......
  • python(django)之单一接口管理功能后台开发
    1、创建数据模型在apitest/models.py下加入以下代码classApis(models.Model):Product=models.ForeignKey('product.Product',on_delete=models.CASCADE,null=True)#关联产品IDapiname=models.CharField('接口名称',max_length=100)apiurl=mod......