Go新项目-Gin中wire的依赖注入方式实战(6)

在这里插入图片描述

选型Go项目过程中,针对依赖注入方式的分析和使用

参考资料

  • https://go.dev/blog/wire
  • https://medium.com/@dche423/master-wire-cn-d57de86caa1b
  • https://toutiao.io/posts/et0t2lk/preview
  • https://imlht.com/archives/223/
  • https://lailin.xyz/post/go-training-week4-wire.html
  • https://luenci.me/2022/01/08/%E8%81%8A%E8%81%8AWire%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/
  • http://c.biancheng.net/view/78.html
  • https://zhuanlan.zhihu.com/p/338926709
  • https://github.com/DuanJiaNing/thewaytowire

wire与其他同类工具的对比

Wire 是一个轻巧的Golang依赖注入工具。它由Go Cloud团队开发,通过自动生成代码的方式在编译期完成依赖注入。

依赖注入是保持软件 “低耦合、易维护” 的重要设计准则之一

同类型哦工具有:来自Uber 的 dig 、来自Facebook 的 inject,下边我们只对比下wire和dig

wire和dig的区别

uber 推出的依赖注入库,采用反射,在运行时计算依赖关系,构造依赖对象。

上面简单介绍了wire 和 dig 两者之间的特点:
1、dig 通过反射识别依赖关系,wire 是编译前计算依赖关系
2、dig 只能在代码运行时,才能知道哪个依赖不对,比如构造函数返回类型的是结构体指针,但是其他依赖的是interface,这样的错误只能在运行时发现,而wire可以在编译的时候就发现。
3、由于采用了依赖注入,所以在代码调试时可以注入一些mock 服务或者函数,wire在mock上支持更友好些,dig的话可以通过build tag 来使用mock。 个人比较推荐使用wire,可以在编译时就发现问题,避免了 多次的build和尝试后才解决编译问题。更多的使用方式和最佳实践,可以参考官方文档。
根据依赖倒置原则(Dependence Inversion Principle),对象应当依赖于接口,而不是直接依赖于具体实现。

使用wire的优势:

  • 方便debug,若有依赖缺失编译时会报错
  • 因为不需要 Service Locators, 所以对命名没有特殊要求
  • 避免依赖膨胀。生成的代码只包含被依赖的代码,而运行时依赖注入则无法作- 到这一点
  • 依赖关系静态存于源码之中, 便于工具分析与可视化

wire 中的两个核心概念: Provider 和 Injector

provider: a function that can produce a value. These functions are ordinary Go code.
injector: a function that calls providers in dependency order. With Wire, you write the injector’s signature, then Wire generates the function’s body.

  • Provider 是一个生成组件的普通函数,这个函数会返回构建依赖关系所需的组件。
  • Injector 是很多个 Provider 组装在一起的时候,可以得到一个管理对象,由wire自动生成的函数。函数内部会按根据依赖顺序调用相关privoder 。

使用wire实战

安装

  • 一、仓库地址:https://github.com/google/wire
  • 二、使用方法:
  • 1、执行 go get github.com/google/wire/cmd/wire 命令
  • 2、执行 go install github.com/google/wire/cmd/wire@latest 命令
  • 3、确认gopath中bin是否存在wire.exe或wire
  • 三、我们的代码目录结构
    route -->> controller–> service -->>Idao -->>dao ->>model

用法效果对比

wire 依赖注入方式想要达到的效果:

我们有一个主函数:

func main() {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)

event.Start()
}

我们改成这样:

func main() {
event := InitializeEvent()
event.Start()
}

代码目录结构

├── routes
│   ├── init_server.go
│   ├── routes.go
│   ├── wire.go
│   └── wire_gen.go

第一步:编写wire.go

//go:build wireinject
// +build wireinject

package routes


import (
"gdonline_backend/databases/redis"
"github.com/google/wire"
"github.com/rs/zerolog"
"gorm.io/gorm"

"gdonline_backend/internal/controller"
"gdonline_backend/internal/dao"
"gdonline_backend/internal/service"
)

var chpoPhenotype = wire.NewSet(
dao.NewChpoPhenotypeDao,
wire.Bind(new(dao.IChpoPhenotypesDao), new(*dao.ChpoPhenotypesDao)),
service.NewChpoPhenotypeService,
controller.NewChpoPhenotypesController,
)

func InitChpoPhenotypes(db *gorm.DB, log *zerolog.Logger) *controller.ChpoPhenotypesController {
panic(wire.Build(chpoPhenotype))
}

第二步:wire

第三步:生成 wire_gen.go

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package routes

import (
"gdonline_backend/databases/redis"
"gdonline_backend/internal/controller"
"gdonline_backend/internal/dao"
"gdonline_backend/internal/service"
"github.com/google/wire"
"github.com/rs/zerolog"
"gorm.io/gorm"
)

// Injectors from wire.go:

func InitChpoPhenotypes(db *gorm.DB, log *zerolog.Logger) *controller.ChpoPhenotypesController {
chpoPhenotypesDao := dao.NewChpoPhenotypeDao(db, log)
chpoPhenotypesService := service.NewChpoPhenotypeService(chpoPhenotypesDao)
chpoPhenotypesController := controller.NewChpoPhenotypesController(chpoPhenotypesService)
return chpoPhenotypesController
}

// wire.go:

var chpoPhenotype = wire.NewSet(dao.NewChpoPhenotypeDao, wire.Bind(new(dao.IChpoPhenotypesDao), new(*dao.ChpoPhenotypesDao)), service.NewChpoPhenotypeService, controller.NewChpoPhenotypesController)


第四步:main.go 中调用

# routes>init_server.go

func InitServer() {
// 初始化数据库连接
db := mysql.DB
redisDB := redis.DB
zeroLog := logging.NewZerolog("business")

// 注册服务-wire
cc = InitChpoPhenotypes(db, zeroLog)

}

# main.go
routes.InitServer()


第五步:实际调用的路由

func Routes(r *gin.Engine) {
// 设置路由组: v1
v1 := r.Group("v1")
chpoPhenotype := v1.Group("chpo_phenotypes")
// 知识库管理
chpoPhenotype.GET("lists", cc.Lists)    // 列表接口
chpoPhenotype.GET("detail", cc.Detail)  // 获取表型详情
chpoPhenotype.POST("add", cc.Add)       // 新增
chpoPhenotype.POST("edit", cc.Edit)     // 编辑
chpoPhenotype.POST("delete", cc.Delete) // 删除
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/340528.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

右值引用和move语义

文章目录 一、左值和右值二、左值引用和右值引用三、move语义四、右值引用的作用1.左值引用的作用和局限2.右值引用的作用3.重谈std::move()4.完美转发 一、左值和右值 在《C Primer Plus》书中这样提到左值:左值是用于标识或定位存储位置的标签。 对于早期的 C 语…

Kafka框架详解

Kafka 1、Kafka介绍 ​ Kafka是最初由linkedin公司开发的,使用scala语言编写,kafka是一个分布式,分区的,多副本的,多订阅者的消息队列系统。 2、Kafka相比其他消息队列的优势 ​ 常见的消息队列:Rabbit…

【设计模式】张一鸣笔记:责任链接模式怎么用?

我将通过一个贴近现实的故事——请假审批流程,带你了解和掌握责任链模式。 什么是责任链模式? 责任链模式是一种行为设计模式,它让你可以避免将请求的发送者与接收者耦合在一起,让多个对象都有处理请求的机会将这个对象连成一条…

MQ 消息丢失、重复、积压问题,如何解决?

面试官在面试候选人时,如果发现候选人的简历中写了在项目中使用了 MQ 技术(如 Kafka、RabbitMQ、RocketMQ),基本都会抛出一个问题:在使用 MQ 的时候,怎么确保消息 100% 不丢失? 这个问题在实际…

2024-01-22(MongoDB)

1.Mongodb使用的业务场景: 传统的关系型数据库/mysql在“三高”需求以及应对web2.0的网站需求面前,有点力不从心,什么是“三高”需求: a. 对数据库高并发的读写需求 b. 对海量数据的高效率存储和访问需求 c. 对数据库的高可扩…

wayland(wl_shell) + egl + opengles 实例——gears

文章目录 前言一、ubuntu 上 opengl 版本的 glxgears二、基于 wayland 窗口协议的 gles-gears1.egl_wayland_gears.c2. matrix.c 和 matrix.h3. 编译4. 运行总结参考资料前言 本文主要介绍如何在linux 下 wayland 窗口中,使用 egl + opengles 控制GPU 渲染 gears 并显示,即实…

element plus表格的表头和内容居中

文章目录 需求分析 需求 对于 element-plus 中的 table 进行表头和内容的居中显示 分析 单列的表头和内容居中 &#xff1a; 在对应的那一列加上align“center” 即可 <el-table-column prop"name" label"商品名称" align"center" />…

统计灰度图像的灰度值分布并绘制

1、numpy方法 函数&#xff1a; numpy.histogram(a, bins10, rangeNone, normedNone, weightsNone, densityNone) 参数说明&#xff1a; a:输入数据数组&#xff1b;bins:指定统计的区间个数&#xff0c;可以是一个整数&#xff0c;也可以是一个数组&#xff0c;默认值为10…

华而有实,维乐Prevail Glide带你领略风景线,成为风景线~

大家都知道呢&#xff01;骑行&#xff0c;不仅是一种运动&#xff0c;更是一种生活态度。在骑行装备的世界里&#xff0c;一个好的坐垫对于骑行的舒适度和安全性至关重要。那今天&#xff0c;我要为大家推荐一款备受赞誉的坐垫——维乐坐垫美学系列-Prevail Glide。    为…

【C++】初识类和对象

引言 在C语言中&#xff0c;我们用结构体来描述一个复杂的对象&#xff0c;这个对象可能包括许多的成员&#xff0c;如用结构体描述一个学生的成绩&#xff0c;或者描述一个日期等。 struct Date {int _year;int _month;int _day; }; 如上是一个描述日期的结构体定义&#x…

一本满是错误的Go语言书,凭什么1000万人都在读

犯错是每个人生活的一部分。正如爱因斯坦曾说过&#xff1a;一个从未犯过错的人从未尝试过新东西。 最重要的不是我们犯了多少错误&#xff0c;而是我们从错误中学到了多少东西。 这个观点同样适用于编程领域。 我们从一门编程语言中获取经验不是一个神奇的过程&#xff0c;…

Rocky Linux 9. 3安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

2024.1.19 网络编程 作业

思维导图 练习题 1> UDP传输实现聊天室 服务器端 #include <myhead.h> #define SER_IP "192.168.125.151" #define SER_PORT 9999 typedef struct Msg {char user[32]; //用户名int type; //执行操作1.登录、2.发消息、0.退出char text[1024]; …

NOC总线(1)

1. 背景 SoC &#xff08;system on chip,片上系统&#xff09;通常指在单一芯片上实现的数字计算机系统&#xff0c;总线结构是该系统的主要特征&#xff0c;由于其可以提供高性能的互连而被广泛运用。随着单芯片上集成的处理器核数越来越多&#xff0c;片上互连架构经历了从专…

sqlmap使用教程(2)-连接目标

目录 连接目标 1.1 设置认证信息 1.2 配置代理 1.3 Tor匿名网络 1.4 检测WAF/IPS 1.5 调整连接选项 1.6 处理连接错误 连接目标 场景1&#xff1a;通过代理网络上网&#xff0c;需要进行相应配置才可以成功访问目标主机 场景2&#xff1a;目标网站需要进行身份认证后才…

【git分支管理策略】

文章目录 前言一、分支管理策略简介二、git基本操作三、git分支远程分支本地分支 四、gitflow分支管理策略分支定义gitflow分支管理策略评价 五、GITHUB FLOW分支管理策略分支使用流程创建分支&#xff08;Create a branch&#xff09;新增提交(add and commit)提出 Pull 请求&…

关联系统-智能座舱控制器ICC

智能座舱构成 如上图所示&#xff0c;智能座舱主要是由仪表、中控、HUD、语音、DMS/OMS等多种交互通道组成&#xff0c;其宗旨是提升人的交互体验&#xff0c;使车辆更加智能化&#xff0c;情感化。 智能座舱内部功能 仪表功能 SR场景重构 如上图所示&#xff0c;仪表区域可实…

k8s的包管理工具helm

Helm是什么? 之前的这篇文章介绍了一开始接触k8s的时候接触到的几个命令工具 kubectl&kubelet&rancher&helm&kubeadm这几个命令行工具是什么关系&#xff1f;-CSDN博客 Helm 是一个用于管理和部署 Kubernetes 应用程序的包管理工具。它允许用户定义、安装和…

Linux软件包管理器yum

文章目录 前言概述Linux下载软件的三种方式源代码安装rpm安装yum安装 关于yum的相关操作查看软件包软件安装卸载软件 yum源问题 前言 在Windows系统中&#xff0c;如果我们要去下载软件&#xff0c;我们可以在该软件的官网中进行下载&#xff0c;或者在微软的额软件商店进行下…

设计亚马逊按销售排名功能

1&#xff1a; 定义 Use Cases 和 约束 Use cases 作用域内的Use Case Service 通过目录计算过去一周内最受欢迎的产品User 通过目录去View过去周内最受欢迎的产品Service 有高可用 作用域外 整个电商网站 设计组件&#xff08;只是计算销售排名&#xff09; 约束和假设…