go微服务框架kratos学习笔记八 (kratos的依赖注入)
go微服务框架kratos学习笔记八(kratos的依赖注入)
笔记二提过依赖注入,和如何生成,但没有细讲,本文来简单看看kratos的依赖注入。
什么是依赖注入
先来看一个小程序,
创建一个小程序模拟迎宾员问候客人的事件
我们将创建三个结构类型:
1)为迎宾员创建消息 message
2)表达消息的迎宾员 greeter
3)迎宾员问候客人的事件 event
type Message string
type Greeter struct {
// ... TBD
}
type Event struct {
// ... TBD
}
Message
仅仅携带一条string,现在我们创建一个简单初始器
func NewMessage() Message {
return Message("Hi there!")
}
我们的Greeter
将需要引用这条消息,让我们创建一条初始器给Greeter
func NewGreeter(m Message) Greeter {
return Greeter{Message: m}
}
type Greeter struct {
Message Message // <- adding a Message field
}
在这个初始器中我们分配了Message
字段给Greeter
,现在我们能用Greeter
的方法Greet
来得到一条Message
func (g Greeter) Greet() Message {
return g.Message
}
下一步,我们同样也需要一个初始器用Event
来创建一个Greeter
。
func NewEvent(g Greeter) Event {
return Event{Greeter: g}
}
type Event struct {
Greeter Greeter // <- adding a Greeter field
}
添加一个Start()
来启动事件
func (e Event) Start() {
msg := e.Greeter.Greet()
fmt.Println(msg)
}
Start
即是我们小程序的核心,它告诉greeter
去放出一条问候并打印出来。
现在我们小程序所有的组件就绪了,看看它是如何初始化所有组件的,它看起来可能是这样的
func main() {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)
event.Start()
}
首先我们创建一条message
,然后我们用message
创建一个greeter
,最后我们用greeter
创建一个event
.
这其实就是依赖注入dependency injection简称di的原理,
依赖注入基本上就是提供对象需要的对象(其依赖),而不是让对象自己构造它们。
依赖注入能让测试变的更为简单,我们可以通过构造函数来进行注入。
SomeClass() has its constructor as following:
public SomeClass() {
myObject = Factory.getObject();
}
例如,如果myObject
包含复杂的任务像磁盘访问或者网络访问,那么SomeClass
将很难进行单元测试。程序必须模仿myObject
并且需要模仿Factory
调用
而将myObject
作为参数传递给构造函数.
public SomeClass (MyClass myObject) {
this.myObject = myObject;
}
myObject
就能直接运行,使测试变的更为简单。
可以通过多种方式将依赖项注入到对象中(例如构造函数注入或setter注入)。甚至可以使用专门的依赖项注入框架(例如Spring)来做到这一点,但是肯定不是必需的。不需要那些框架的依赖注入。显式实例化和传递对象(依赖项)与框架注入一样好。
google wire
kratos 使用的 google wire 就是golang的一个依赖注入解决的工具,这个工具能够自动生成类的依赖关系。
依赖注入的一个缺点就是需要如此多的初始化步骤,让我们看看如何使用Wire来让初始化我们的组件变的更快.
将我们的小程序main函数改成如下形式:
func main() {
e := InitializeEvent()
e.Start()
}
下一步,分离一个文件wire.go,我们定义InitializeEvent
// wire.go
func InitializeEvent() Event {
wire.Build(NewEvent, NewGreeter, NewMessage)
return Event{}
}
不是依次初始化每个组件并将其传递给下一个组件,而是通过一个 wire.Build
调用来构建我们想要的用的初始器。在Wire
中,初始化器被称为providers
,一个提供特定类型的函数。
我们为Event
添加一个零值作为返回值,以满足编译器的要求。
注意,即使我们向Event
添加值,Wire也会忽略它们。
实际上,注入器的目的是提供关于使用哪些providers
来构造Event
的信息。
InitializeEvent
即是一个“注入器”。现在我们已经完成了注入器
然后在wire.go目录下运行wire工具。
安装
:
go get github.com/google/wire/cmd/wire
Wire
将找到InitializeEvent
注入器并生成一个函数,其主体由所有必要的初始化步骤填充。结果将被写入名为wire_gen.go的文件。
// wire_gen.go
func InitializeEvent() Event {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)
return event
}
这看上去就像我们上面手工写的代码,想象一下,对于复杂得多的组件,Wire是多么有用。
kratos中的wire
最后回来看看kratos中的wire.go
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package di
import (
pb "demo/api"
"demo/internal/dao"
"demo/internal/server/grpc"
"demo/internal/server/http"
"demo/internal/service"
"github.com/google/wire"
)
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, http.New, grpc.New, NewApp))
}
可以看到kratos用到了wire的一些其它接口:wire.NewSet
,wire.Bind
,简单看看。
wire.NewSet
Wire
有两个核心概念:Providers
和injectors
。
Providers
Wire中的主要机制是Providers
:一个可以生成值的函数。这些函数都是普通的Go代码。
Providers
可以分组为provider sets
,通过wire.NewSet
函数可以添加一组providers
到一个新的集合中。
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)
当然也可以添加一个provider sets
进一个provider sets
var MegaSet = wire.NewSet(daoProvider, pkg.OtherSet)
injector(注入器)
一个应用程序用injector
连接这些providers
: 一个按依赖顺序调用providers
的函数,即使用Wire,编写注入器的签名,然后Wire生成函数的主体。
调用wire.Build
的函数则是来声明注入器的,返回值不重要,只要类型正确即可。
func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, http.New, grpc.New, NewApp))
}
Binding Interfaces
最后看看 wire.Bind
用来绑定接口的具体类型。
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
wire.Bind第一个参数 为指向所需接口类型的指针,第二个参数为 指向实现该接口类型的指针,
可以看到如果不加wire.Bind(new(pb.DemoServer), new(*service.Service)), 可以看到会找不到依赖。
go微服务框架kratos学习笔记八 (kratos的依赖注入)的更多相关文章
- go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时])
目录 go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时]) 静态配置 flag注入 在线热加载配置 远程配置中心 go微 ...
- # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)
目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...
- go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer)
目录 go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer) demo demo server demo client 池 dao service p2c ro ...
- go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用)
目录 go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用) warden direct demo-server gr ...
- go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin)
目录 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin) zipkin使用demo 数据持久化 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin ...
- 微服务框架surging学习之路——序列化 (转载https://www.cnblogs.com/alangur/p/10407727.html)
微服务框架surging学习之路——序列化 1.对微服务的理解 之前看到在群里的朋友门都在讨论微服务,看到他们的讨论,我也有了一些自己的理解,所谓微服务就是系统里的每个服务都 可以自由组合.自由组 ...
- golang微服务框架go-micro 入门笔记2.4 go-micro service解读
本章节阐述go-micro 服务发现原理 go-micro架构 下图来自go-micro官方 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...
- golang微服务框架go-micro 入门笔记2.3 micro工具之消息接收和发布
本章节阐述micro消息订阅和发布相关内容 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架go-mi ...
- golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web
micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...
随机推荐
- 在GeneXus开发过程中如何进行自动化测试?
1. 简介 GXtest是基于专门为GeneXus平台开发的应用程序提供的自动化测试解决方案. 我们强调“解决方案”和“自动化”两个词: 解决方案:GXtest为整个GeneXus软件开发生命周期提供 ...
- 快速搭建一个自己的个人博客(Github Pages~二次元主题)
前言 本次的一个布局技术都写的非常详细了,只要按着来就行,不过,先说明本次主题为二次元主题. 如果真的喜欢本主题的不妨可以试一试(==建议跟据目录来看==) 在很久很久以前.... 嘛,就在前不久我正 ...
- C#实现文件Move操作和文件的Copy操作
文件移动(Move)操作和文件的复制(Copy)是C#程式开发经常遇到的方法,根据传入的源文件地址和目标文件地址参数,实现对文件的操作.实现代码如下: Move操作代码: public static ...
- python循环语句(while和for)
循环语句分成两种,while循环 和 for循环 作用:可以使指定的代码块重复指定的次数 while循环: # 语法: # while 条件表达式 : # 代码块 # else : # 代码块 # 执 ...
- Core 定时任务之TimeJob
第一:引入NuGet包: Install-Package Pomelo.AspNetCore.TimedJob -Version -rtm- 第二: 在StartUp 中注册Job: public c ...
- 百度DMA+小度App的蓝牙语音解决方案案例展示
前记 跟着百度也有一段时间了,经过一年多的努力,我们也做出了一些产品.下面就给大家秀一下我们做的产品.有类似需求的朋友可以多多交流. 智能语音耳机 这个是就是可以通过按键来调用小度app的运动 ...
- 世界上最流行的版本控制系统——Git
版本控制系统,也就是VCS(Version Control System),可以说是程序员必备的工具.那么它到底是什么,有什么作用呢? 举个例子,如果你想查看你所开发的软件在一个月之前的模样,同时还想 ...
- 盘它!!一步到位,Tensorflow 2的实战 !!LSTM下的股票预测(附详尽代码及数据集)
关键词:tensorflow2.LSTM.时间序列.股票预测 Tensorflow 2.0发布已经有一段时间了,各种新API的确简单易用,除了官方文档以外能够找到的学习资料也很多,但是大都没有给出实战 ...
- C# 调用word进程操作文档关闭进程
C# 调用word进程操作文档关闭进程 作者:Jesai 时间:2018-02-12 20:36:23 前言: office办公软件作为现在主流的一款办公软件,在我们的日常生活和日常工作里面几乎每天都 ...
- 彻底理解Future模式
先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线 ...