当前位置: 首页 > 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…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

学习一下用鸿蒙​​DevEco Studio HarmonyOS5实现百度地图

在鸿蒙&#xff08;HarmonyOS5&#xff09;中集成百度地图&#xff0c;可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API&#xff0c;可以构建跨设备的定位、导航和地图展示功能。 ​​1. 鸿蒙环境准备​​ ​​开发工具​​&#xff1a;下载安装 ​​De…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中&#xff0c;如何展示好看的实验结果图像非常重要&#xff01;&#xff01;&#xff01; 1、灰度原始图像 灰度图像每个像素点只有一个数值&#xff0c;代表该点的​​亮度&#xff08;或…...