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

Gone框架介绍27 - 再讲 Goner 和 依赖注入

gone是可以高效开发Web服务的Golang依赖注入框架
github地址:https://github.com/gone-io/gone
文档地址:https://goner.fun/zh/

文章目录

  • Goner 和 依赖注入
    • Goner的定义
    • 依赖标记
    • Goners 注册
    • Priest函数

Goner 和 依赖注入

Gone 作为一个依赖注入框架,首先需要回答的问题:什么是依赖,如何定义依赖?

在golang中已经定义了package,我们在项目中引入的package就是一种依赖;这些依赖可以利用golang项目中的.mod文件进行比较好的管理,然而这种依赖也并不是我们讨论的需要注入的依赖。

“依赖注入”,作为一个动补短语,要明确它的含义,需要问:什么依赖了什么,谁注入了谁?

在golang中,能够承载业务逻辑的结构,只有 funcstructfunc 的执行结果 依赖 函数的参数,而 struct 功能的实现 依赖 结构体的属性。无论是函数的参数 还是 结构体的属性,都是业务逻辑实现的 依赖;这样我们就回答了“什么是依赖?”:

定义

依赖,是为了实现某业务逻辑,函数或者结构体需要依赖的 外部值 或者 外部参数。

这些外部值或者外部参数,可能是代表了业务逻辑依赖的外部业务;实现我们的业务所需的业务逻辑,需要依赖这些外部业务来完成。由此可见,是 业务 依赖了 业务,那么注入的也是业务,是 业务 注入了 业务

为了对业务进行抽象,我们定义了Goner,它是一个接口,所有业务结构体都要实现它;那么,在Gone框架中,就是 Goners依赖Goners,Goners注入到Goners

Goner的定义

我们查看Goner的定义,如下:

type Goner interface {goneFlag()
}

可以看到,Goner是一个接口,要求实现一个私有方法goneFlag(),这个方法是为了标识该结构体是Goner。由于golang语法限制,在包外部是无法实现一个包内的私有方法的,为了在外部的业务代码可以实现 Goner接口 ,我们又定义了gone.Flag结构体,并且在实现了goneFlag()方法时将方法的接收者设置了为 Flag指针,如下:

type Flag struct{}func (g *Flag) goneFlag() {}

这样,业务结构体XBusiness 有且仅有 匿名嵌入gone.Flag才能完成对Goner接口的实现。gone框架要求只有Goner才可以被注册到Gone框架中,用于依赖注入的装配。
例如:

package exampleimport "github.com/gone-io/gone"type XBusiness struct {gone.Flag
}

这样设计的好处是:

  1. 限定依赖注入装配的对象都是Goner,可以简化了依赖注入装配流程实现。
  2. 限定Goner一定是指针,依赖注入时可以避免结构体的值拷贝;一方面是提高性能,另一方面是避免值拷贝时的“浅拷贝”业务对象带来的未知问题。

依赖标记

业务结构体中,并不是所有的属性都需要依赖注入,需要有一种机制标记哪些属性需要使用依赖注入。为此,我们设计了标签gone来标记需要注入的属性,如下:

type Employee interface {Work()
}type Company struct {gone.FlagBoss Employee `gone:"*"` // 标记需要依赖注入的属性
}

公司需要注入一个员工作为Boss,星号(*)表示该属性的注入只需要匹配类型,即实现 Employee 接口的Goner就可以;这种注入方式,我们称为匿名注入

需要注意

Goner 结构体需要注入的属性,可以是任意 接口 或者 结构体指针,这里并不限定是Goner,只有Goner注册到Gone框架时限定Goner类型。

公司的老板不可能是任何员工都能担任的,与匿名注入对应的就是具名注入,注入标签可以将星号替换为需要注入Goner的Id 字符串,如下:

type Company struct {gone.FlagBoss Employee `gone:"boss"` // 具名注入,要求该属性注入一个Id=boss的Goner
}

Goners 注册

为了完成依赖注入的自动装配,我们需要将所有的Goners注册到Gone框架中。下面给出上面公司依赖员工这个例子的完整代码,如下:

package mainimport ("fmt""github.com/gone-io/gone"
)type Employee interface {Work()Name() string
}type Company struct {gone.FlagBoss Employee `gone:"boss"` // 标记需要依赖注入的属性
}func (c *Company) Start() {fmt.Printf("Company start, boss is %s\n", c.Boss.Name())c.Boss.Work()
}type EmployeeImpl struct {gone.Flagname string
}func (e *EmployeeImpl) Work() {fmt.Printf("I am working, my name is %s\n", e.Name())
}func (e *EmployeeImpl) Name() string {return e.name
}func main() {gone.Prepare(func(cemetery gone.Cemetery) error {//注册EmployeeImplcemetery.Bury(&EmployeeImpl{name: "Scott"}, gone.GonerId("boss"))//注册Companycemetery.Bury(&Company{})return nil}).Run(func(company *Company) {company.Start()})
}

可以看到,我们使用了cemetery.Bury 方法完成了Goner到Gone框架的注册;该方法第二参数可以指定被注册的Goner的Id,如果没有指定Id,Gone框架会自动为Goner随机生成一个Id。在具名注入时,我们会用到注册时的GonerId来作为gone标签的值。

Priest函数

在上面代码中,gone.Prepare 方法接收的参数为一个匿名函数,它的形式如下:

func(cemetery Cemetery) error

在Gone框架中,这样形式的函数被定义为Priest函数,专门负责Goners的注册。

Priest的定义

type Priest func(cemetery Cemetery) error

大多数情况下,我们可以不用手动编写Priest代码;在gone中提供了 gone辅助工具,可以为我们自动生成Priest函数代码:自动生成Priest

相关文章:

Gone框架介绍27 - 再讲 Goner 和 依赖注入

gone是可以高效开发Web服务的Golang依赖注入框架 github地址:https://github.com/gone-io/gone 文档地址:https://goner.fun/zh/ 文章目录 Goner 和 依赖注入Goner的定义依赖标记Goners 注册Priest函数 Goner 和 依赖注入 Gone 作为一个依赖注入框架&am…...

【Python/Pytorch 】-- 滑动窗口算法

文章目录 文章目录 00 写在前面01 基于Python版本的滑动窗口代码02 算法效果 00 写在前面 写这个算法原因是:训练了一个时序网络,该网络模型的时序维度为32,而测试数据的时序维度为90。因此需要采用滑动窗口的方法,生成一系列32…...

Clickhouse集群create drop database可删除集群数据库或只删除本地数据库

集群环境下,在任意一个节点创建数据库,如果加上了ON CLUSTER clustername,则在集群环境的所有节点上都创建了该数据库,并在集群环境的所有节点上都创建了该数据库对应的目录,且数据库的metadata_path对应的目录路径在所…...

【docker】adoptopenjdk/openjdk8-openj9:alpine-slim了解

adoptopenjdk/openjdk8-openj9:alpine-slim 是一个 Docker 镜像的标签,它指的是一个特定的软件包,用于在容器化环境中运行 Java 应用程序。 镜像相关的网站和资源: AdoptOpenJDK 官方网站 - AdoptOpenJDK 这是 AdoptOpenJDK 项目的官方网站&…...

Vscode interaction window

python 代码关联到 jupyter 模式 在代码前添加: # %%print("hellow wolrd!") 参考文档链接: https://code.visualstudio.com/docs/python/jupyter-support-py...

后端数据null前端统一显示成空

handleNullValues方法在封装请求接口返回数据时统一处理 // null 转 function handleNullValues(data) {// 使用递归处理多层嵌套的对象或数组function processItem(item) {if (Array.isArray(item)) {return item.map(processItem);} else if (typeof item object &&…...

【设计模式深度剖析】【9】【行为型】【访问者模式】| 以博物馆的导览员为例加深理解

👈️上一篇:备忘录模式 | 下一篇:状态模式👉️ 设计模式-专栏👈️ 文章目录 访问者模式定义英文原话直译如何理解呢? 访问者模式的角色类图代码示例 访问者模式的应用优点缺点使用场景 示例解析:博物馆的导览员代码示例 访问…...

Salesforce‘s 爱因斯坦机器人助手引领工业聊天机器人时代

CRM的对话式人工智能助手,根据公司数据提供可靠的人工智能响应及日本工业聊天机器人现状 【前言】 爱因斯坦助手(Einstein Copilot)提供可靠的响应,因为它基于公司独特的数据和元数据,使其能够深入了解公司的业务和客…...

Day7—zookeeper基本操作

ZooKeeper介绍 ZooKeeper(动物园管理员)是一个分布式的、开源的分布式应用程序的协调服务框架,简称zk。ZooKeeper是Apache Hadoop 项目下的一个子项目,是一个树形目录服务。 ZooKeeper的主要功能 配置管理 分布式锁 集群管理…...

计算机组成原理---Cache的基本工作原理习题

对应知识点: Cache的基本原理 1.某存储系统中,主存容量是Cache容量的4096倍,Cache 被分为 64 个块,当主存地址和Cache地址采用直接映射方式时,地址映射表的大小应为()(假设不考虑一致维护和替…...

springboot项目中切数据库(mysql-> pg)带来的适配问题:typeHandler

一、数据表中有一张表,名为role_permission,DDL如下: CREATE TABLE "public"."role_permission" ( "role_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, "permiss…...

从零开始的<vue2项目脚手架>搭建:vite+vue2+eslint

前言 为了写 demo 或者研究某些问题,我经常需要新建空项目。每次搭建项目都要从头配置,很麻烦。所以我决定自己搭建一个项目初始化的脚手架(取名为 lily-cli)。 脚手架(scaffolding):创建项目时…...

Hadoop升级失败,File system image contains an old layout version -64

原始版本 Hadoop 3.1.3 升级版本 Hadoop 3.3.3 报错内容如下 datasophon 部署Hadoop版本 查看Hadoop格式化版本 which hadoop-daemon.sh/bigdata/app/hadoop-3.1.3/sbin/hadoop-daemon.sh删除原来的旧版本 rm -rf /bigdata/app/hadoop-3.1.3查看环境变量 env|grep HADOOPHAD…...

[机器学习算法]决策树

1. 理解决策树的基本概念 决策树是一种监督学习算法,可以用于分类和回归任务。决策树通过一系列规则将数据划分为不同的类别或值。树的每个节点表示一个特征,节点之间的分支表示特征的可能取值,叶节点表示分类或回归结果。 2. 决策树的构建…...

springboot应用cpu飙升的原因排除

1、通过top或者jps命令查到是那个java进程, top可以看全局那个进程耗cpu,而jps则默认是java最耗cpu的,比如找到进程是196 1.1 top (推荐)或者jps命令均可 2、根据第一步获取的进程号,查询进程里那个线程最占用cpu,发…...

反激开关电源EMI电路选型及计算

EMI :开关电源对电网或者其他电子产品的干扰 EMI :传导与辐射 共模电感的滤波电路,La和Lb就是共模电感线圈。这两个线圈绕在同一铁芯上,匝数和相位都相 同(绕制反向)。 这样,当电路中的正常电流(差模&…...

vue3前端对接后端的图片验证码

vue3前端对接后端的图片验证码 <template> <image :src"captchaUrl" alt"图片验证码" click"refreshCaptcha"></image> </template><script setup>import {ref} from "vue";import {useCounterStore} …...

【Unity】RPG2D龙城纷争(四)要诀、要诀数据集

更新日期&#xff1a;2024年6月20日。 项目源码&#xff1a;第五章发布&#xff08;正式开始游戏逻辑的章节&#xff09; 索引 简介要诀数据集&#xff08;AbilityDataSet&#xff09;一、定义要诀数据集类二、要诀属性1.要诀类型2.攻击距离3.基础命中、暴击率4.基础属性加成5.…...

一种基于非线性滤波过程的旋转机械故障诊断方法(MATLAB)

在众多的旋转机械故障诊断方法中&#xff0c;包络分析&#xff0c;又称为共振解调技术&#xff0c;是目前应用最为成功的方法之一。首先&#xff0c;对激励引起的共振频带进行带通滤波&#xff0c;然后对滤波信号进行包络谱分析&#xff0c;通过识别包络谱中的故障相关的特征频…...

HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…...

如果xml在mapper目录下,如何扫描到xml

如果xml在mapper目录下,如何扫描到xml 项目结构 src├── main│ ├── java│ │ └── com│ │ └── bg│ │ ├── Application.java│ │ ├── domain│ │ │ └── User.java│ │ …...

什么是无限铸币攻击?它是如何运作的?

一、无限铸币攻击解释 无限铸币攻击是指攻击者操纵合约代码不断铸造超出授权供应限制的新代币。 这种黑客行为在去中心化金融 (DeFi) 协议中最为常见。这种攻击通过创建无限数量的代币来损害加密货币或代币的完整性和价值。 例如&#xff0c;一名黑客利用了 Paid 网络的智能…...

【Android】怎么使APP进行开机启动

项目需求 在Android系统开启之后&#xff0c;目标app可以在系统开机之后启动。 项目实现 使用广播的方式 首先我们要创建一个广播(这里是启动了一个Service服务) public class BootReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context context, I…...

详细分析Element Plus的el-pagination基本知识(附Demo)

目录 前言1. 基本知识2. Demo3. 实战 前言 需求&#xff1a;从无到有做一个分页并且附带分页的导入导出增删改查等功能 前提一定是要先有分页&#xff0c;作为全栈玩家&#xff0c;先在前端部署一个分页的列表 相关后续的功能&#xff0c;是Java&#xff0c;推荐阅读&#x…...

ubuntu换镜像源方法

查看ubuntu的版本&#xff0c;不同的版本对应的不同的镜像源 cat /etc/issue Ubuntu 18.04.6 LTS \n \l 先备份一个&#xff0c;防止更改错误 cobol cp /etc/apt/sources.list /etc/apt/sources.list.backup 先进入清华源,搜索ubuntu&#xff0c;点击问号 点进来可以看到可以…...

python flask配置邮箱发送功能,使用flask_mail模块

&#x1f308;所属专栏&#xff1a;【Flask】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点…...

Flask快速入门(路由、CBV、请求和响应、session)

Flask快速入门&#xff08;路由、CBV、请求和响应、session&#xff09; 目录 Flask快速入门&#xff08;路由、CBV、请求和响应、session&#xff09;安装创建页面Debug模式快速使用Werkzeug介绍watchdog介绍快速体验 路由系统源码分析手动配置路由动态路由-转换器 Flask的CBV…...

人工智能指数报告

2024人工智能指数报告&#xff08;一&#xff09;&#xff1a;研发 前言 全面分析人工智能的发展现状。 从2017年开始&#xff0c;斯坦福大学人工智能研究所&#xff08;HAI&#xff09;每年都会发布一份人工智能的研究报告&#xff0c;人工智能指数报告&#xff08;AII&…...

聊聊 Mybatis 动态 SQL

这篇文章&#xff0c;我们聊聊 Mybatis 动态 SQL &#xff0c;以及我对于编程技巧的几点思考 &#xff0c;希望对大家有所启发。 1 什么是 Mybatis 动态SQL 如果你使用过 JDBC 或其它类似的框架&#xff0c;你应该能理解根据不同条件拼接 SQL 语句有多痛苦&#xff0c;例如拼…...

【windows|004】BIOS 介绍及不同品牌电脑和服务器进入BIOS设置的方法

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…...

展厅设计手绘图/seo网站推广企业

我们为什么要学习数据库&#xff1f; 最主要的就是两点&#xff1a;能够反作用于业务和快速分析定位问题 在软件开发中会遇到很多问题&#xff0c;追根究底它就是一个数据库里数据的问题&#xff0c;就比如说我们要去验证注册来源对不对&#xff0c;如果我们不去查库的话&…...

做外贸建网站需要推广吗/广东百度推广的代理商

想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样~。 25%的面试官会在头5分钟内决定面试的结果60%的面试官会在头15分钟内决定面试的结果 一般来说&#xff0c;一场单面的时间在30分钟左右&…...

wordpress缓存机制/名词解释搜索引擎优化

从大漠那看CSS 从小熊 以及各个UED们那看JS&#xff0c;最近开始筹备深入学习 HTML5 CSS3的东西。 酒杯如琉璃&#xff0c;杯盘如翡翠。 #desk{width: 150px;height: 280px;}#demo{width: 100px;height: 200px;opacity: 1;position: relative;}#demo:before{content: "&qu…...

编写一个android应用程序/seo研究中心学员案例

QPushButton QPushButton小部件提供了一个命令按钮。 按钮或命令按钮可能是任何图形用户界面中最常用的小部件。按下&#xff08;或者单击&#xff09;按钮以命令计算机执行某个操作或回答问题。典型的按钮是确定&#xff0c;应用&#xff0c;取消&#xff0c;关闭&#xff0…...

dede本地环境搭建网站/广东搜索引擎优化

有小伙伴由于安装MySQL的时候&#xff0c;疏忽没有选择底层编码方式&#xff0c;采用默认的ASCII的编码格式&#xff0c;于是接二连三的中文转换问题随之而来&#xff0c;就想卸载了重新安装MYSQL&#xff0c;这一卸载倒是出了问题&#xff0c;导致安装的时候安装不上。mysql数…...

一个阿里云服务器可以放几个网站/广告竞价

在win10下安装jdk后&#xff0c;命令行测试java出现could not open XXX\jvm.cfg 解决方法链接:win10安装jdk出现could not open D:\software\JAVA\lib\amd64\jvm.cfg_lin1314yuan的博客-CSDN博客...