快速学Go依赖注入工具wire
Go相对java和C++是较新的语言,但也有诸多优秀特性及生态库。本文介绍大多数软件工程中常用的功能:依赖注入。首先介绍什么是依赖注入,go实现库wire与其他语言的差异。然后通过简单示例实现依赖注入,简化代码、提升可读性。
依赖注入
依赖注入是一种对象接收它所依赖的其他对象(称为依赖项)的技术。通常,接收对象称为客户端,传入(“注入”)对象称为服务。
为了更好理解,下面通过一个简单示例进行说明:
package mainimport ("fmt"
)type Message string
type Greeter struct {Message Message
}
type Event struct {Greeter Greeter
}func GetMessage() Message {return Message("Hello world!")
}func GetGreeter(m Message) Greeter {return Greeter{Message: m}
}func (g Greeter) Greet() Message {return g.Message
}func GetEvent(g Greeter) Event {return Event{Greeter: g}
}func (e Event) Start() {msg := e.Greeter.Greet()fmt.Println(msg)
}func main() {message := GetMessage()greeter := GetGreeter(message)event := GetEvent(greeter)event.Start()
}
上面代码有message, greeter, event;GetMessage函数返回消息,GetGreeter函数接受消息返回greeter,getEvent函数接受返回greeter返回事件。事件还有一个方法start输出消息。
在main函数中,首先创建消息,然后作为依赖传入greeter,最后传给事件。运行程序可以看到输出“Hello world!",这是相对较浅的依赖图,但也能看到其复杂性,这也是依赖注入库wire的价值体现。
Wire简介
Wire是代码依赖工具,它没有采用反射机制或运行时状态,使用Wire可以有效避免手动编写硬代码依赖。Wire在编译时生成源码,官方文档描述: “In Wire, dependencies between components are represented as function parameters, encouraging explicit initialization instead of global variables.” (在Wire中组件之间的依赖关系表示为函数参数,优先采用显式初始化而不是全局变量。)
通过下面命令安装wire:go get github.com/google/wire/cmd/wire;全局安装wire,为后续使用wire命令生成代码:go install github.com/google/wire/cmd/wire
下面我们使用Wire作为依赖注入工具重构上面代码,新增wire.go文件,增加下面代码:
//go:build wireinject
// +build wireinject
package mainimport "github.com/google/wire"func InitializeEvent() Event {wire.Build(GetMessage, GetGreeter, GetEvent)return Event{}
}
首先导入wire,然后创建InitializeEvent函数,该返回在main函数中调用的事件。函数体内调用wire,在构建器方法内传入所有依赖,注意,传入依赖与顺序无关。然后返回空事件,无需担心,所有交给Wire。
注意,文件上面的注释告诉Go在编译时忽略该文件,要确保该注释行后面增加一行空行。
下面是main函数代码:
func main() {event := InitializeEvent()event.Start()
}
现在成功地把main函数代码降为两行。在wire.go代码目录下,执行wire命令,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 !wireinjectpackage main// Injectors from wire.go:func InitializeEvent() Event {message := GetMessage()greeter := GetGreeter(message)event := GetEvent(greeter)return event
}
同样生成的文件上面注释与wire.go文件相比多了!,表示wire在编译时忽略,go编译时启动。这是运行main函数正确输出结果。
带参数依赖
如果需要动态传入消息作为参数呢?下面我们修改GetMessage函数:
func GetMessage(text string) Message {return Message(text)
}
再次运行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 !wireinjectpackage main// Injectors from wire.go:func InitializeEvent(text string) Event {message := GetMessage(text)greeter := GetGreeter(message)event := GetEvent(greeter)return event
}
现在修改main.go代码:
func main() {event := InitializeEvent("Hello Golang")event.Start()
}
运行结果与期望一致。
如果修改wire.go代码, 模拟缺少部分依赖:
func InitializeEvent(text string) Event {wire.Build(GetMessage, GetEvent)return Event{}
}
执行wire命令,会正确提示少了相应的依赖:
inject InitializeEvent: no provider found for demo01.Greeter needed by demo01.Event in provider "GetEvent"
总结
本文介绍了基本wire概念,并通过简单示例介绍动态实现依赖注入。但一般wire会在较大项目使用,更多高级功能参考官方文档:https://github.com/google/wire/blob/main/docs/guide.md#advanced-features 。
相关文章:
快速学Go依赖注入工具wire
Go相对java和C是较新的语言,但也有诸多优秀特性及生态库。本文介绍大多数软件工程中常用的功能:依赖注入。首先介绍什么是依赖注入,go实现库wire与其他语言的差异。然后通过简单示例实现依赖注入,简化代码、提升可读性。 依赖注入…...
python入门(4)流程控制语句
1. 条件判断语句 条件控制语句用于根据条件来决定程序的执行路径。在Python中,常见的条件控制语句有以下几种: (1)if语句:用于执行满足条件的代码块。示例代码: age 20 if age > 18:print("成年…...
【进阶】C 语言表驱动法编程原理与实践
数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条,正确的算法就不言自明。编程的核心是数据结构,而不是算法。——Rob Pike 目录 说明 概念提出 查表方式 直接查找 索引查找 分段查找 实战示例 字符统计 月天校验 名称构造 值名…...
java+springboot留学生新闻资讯网的设计与实现
Spring框架是Java平台的一个开放源代码的Full-stack(全栈)应用程序框架,和控制翻转容器的实现。Spring框架的一些核心功能理论,可以用于所有Java应用,Spring还为Java EE构建的Web应用提供大量的扩展支持。Spring框架没有实现任何的编程模型&a…...
分布式事务与分布式锁区别及概念学习
一、 分布式事务 1.1 背景 传统事务ACID是基于单数据库的本地事务,仅支持单机事务,并不支持跨库事务。但随着微服务架构的普及,业务的分库分表导致一个大型业务系统往往由若干个子系统构成,这些子系统又拥有各自独立的数据库。往往一个业务流程需要由多个子系统共同完成,…...
windows先的conda环境复制到linux环境
如果是迁移的环境一致:同是windows或同是linux直接用这个命令即可: conda create -n new_env_name --clone old_env_path 如果是window的环境迁移到linux这种跨环境就不能用上面的方法,网上这方面的资料也很多,记录一下我的…...
庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>
庄懂的TA笔记(十七)<特效:屏幕UV 屏幕扰动> 大纲: 目录 庄懂的TA笔记(十七)<特效:屏幕UV 屏幕扰动> 大纲: 正文: 一…...
手写简易RPC框架
目录 简介 服务提供者 服务注册:注册中心 HttpServerHandler处理远程调用请求 consumer服务消费端 简介 RPC(Remote Procedure Call)——远程过程调用,它是一种通过网络从远程计算机程序上请求服务, 而不需要了解…...
基于孪生网络的目标跟踪
一、目标跟踪 目标跟踪是计算机视觉领域研究的一个热点问题,其利用视频或图像序列的上下文信息,对目标的外观和运动信息进行建模,从而对目标运动状态进行预测并标定目标的位置。具体而言,视觉目标(单目标)…...
苏州狮山广场能耗管理系统
摘要:随着社会生活水平的提高,经济的繁荣发展,人们对能源的需求逐渐增长,由此带来的能源危机日益严重。商场如何实时的了解、分析和控制商场的能源消耗已成为需要解决的迫在眉睫的难题。传统的能源消耗智能以月/季度/年为周期进行…...
Jupyter Notebook 10个提升体验的高级技巧
Jupyter 笔记本是数据科学家和分析师用于交互式计算、数据可视化和协作的工具。Jupyter 笔记本的基本功能大家都已经很熟悉了,但还有一些鲜为人知的技巧可以大大提高生产力和效率。在这篇文章中,我将介绍10个可以提升体验的高级技巧。 改变注释的颜色 颜…...
CF 751 --B. Divine Array
Black is gifted with a Divine array a consisting of n (1≤n≤2000) integers. Each position in a has an initial value. After shouting a curse over the array, it becomes angry and starts an unstoppable transformation. The transformation consists of infinite…...
Springcloud1--->Eureka注册中心
目录 Eureka原理Eureka入门案例编写EurekaServer将user-service注册到Eureka消费者从Eureka获取服务 Eureka详解基础架构高可用的Eureka Server失效剔除和自我保护 Eureka原理 Eureka:就是服务注册中心(可以是一个集群),对外暴露自…...
面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生
测试员可以先在大厂镀金,以后去中小厂毫无压力,基本不会被卡,事实果真如此吗?但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已,如果面试答得稀烂,人家根本不会要你。况且要不是大厂出来…...
JAVA开发(记一次删除完全相同pgSQL数据库记录只保留一条)
进行数据管理时,无效数据可能会对生产力和决策质量造成严重的影响。如何发现和处理无效数据变得愈发重要。一起来唠唠你会如何处理无效数据吧~ 方向一:介绍无效数据的概念 最近遇到了pg数据库表中的大量数据重复了,需要删除其中的一条。一条…...
音视频八股文(7)-- 音频aac adts三层结构
AAC介绍 AAC(Advanced Audio Coding)是一种现代的音频编码技术,用于数字音频的传输和存储领域。AAC是MPEG-2和MPEG-4标准中的一部分,可提供更高质量的音频数据,并且相比于MP3等旧有音频格式,AAC需要更少的…...
Docker代码环境打包进阶 - DockerHub分享镜像
1. Docker Hub介绍 Docker Hub是一个广泛使用的容器镜像注册中心,为开发人员提供了方便的平台来存储、共享和分发Docker容器镜像。它支持版本控制、访问控制和自动化构建,并提供了丰富的公共镜像库,方便开发人员快速获取和使用各种开源应用和…...
SQL进阶-having子句的力量
SQL进阶-having子句的力量 having子句是理解SQL面向集合这一本质的关键。 在以前的SQL标准里面,having子句必须和group by子句一起使用,但是按照现在的SQL标准,having子句是可以单独使用的 可以与case 表达式或者自连接等结合使用。表不是文件…...
Electron 如何创建模态窗口?
目录 前言一、模态窗口1.Web页面模态框2.Electron中的模态窗口3.区分父子窗口与模态窗口 二、实际案例使用总结 前言 模态框是一种常用的交互元素,无论是在 Web 网站、桌面应用还是移动 APP 中,都有其应用场景。模态框指的是一种弹出窗口,它…...
诺贝尔化学奖:酶分子“定向进化”
2018年,诺贝尔化学奖迎来了历史上第五位女性得主——加州理工学院的Frances H. Arnold教授,以表彰她在“酶的定向进化”这一领域的贡献。 1、“酶的定向进化”到底是什么? 这里有三个点,“酶”、“进化”还有“定向”:…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
