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中,能够承载业务逻辑的结构,只有 func 和 struct,func 的执行结果 依赖 函数的参数,而 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
}
这样设计的好处是:
- 限定依赖注入装配的对象都是Goner,可以简化了依赖注入装配流程实现。
- 限定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龙城纷争(四)要诀、要诀数据集
更新日期:2024年6月20日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介要诀数据集(AbilityDataSet)一、定义要诀数据集类二、要诀属性1.要诀类型2.攻击距离3.基础命中、暴击率4.基础属性加成5.…...
一种基于非线性滤波过程的旋转机械故障诊断方法(MATLAB)
在众多的旋转机械故障诊断方法中,包络分析,又称为共振解调技术,是目前应用最为成功的方法之一。首先,对激励引起的共振频带进行带通滤波,然后对滤波信号进行包络谱分析,通过识别包络谱中的故障相关的特征频…...
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现(一) HarmonyOS Next 系列之验证码输入组件实现(二) HarmonyOS Next 系列之底部标签栏TabBar实现(三) HarmonyOS Next 系列之HTTP请求封装和Token…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
