最近在开发基于golang下的cqrs框架 https://github.com/berkaroad/squat (陆续开发中,最近断了半年,懒了。。。)。这个框架依赖ioc框架,因为之前写了一个ioc,所以借此完善下,主要从灵活性、易用性、性能角度进行了优化。顺带也支持了go mod,并将源码文件合并为单文件,方便有直接移植源码的人(license信息请保留,尊重著作权)。

  先来个直观的调用端对比(v1.2.0为新版,v0.1.1为旧版):

var container = ioc.NewContainer() // v0.1.1
var container = ioc.New() // v1.2.0,非必需,可以直接使用ioc.XXX 即使用内置全局Container // register service to *struct
container.Register(&Class2{Name: "Jerry Bai"}, ioc.Singleton) // v0.1.1
ioc.AddSingleton[*Class2](&Class2{Name: "Jerry Bai"}) // v1.2.0
container.Register(&Class1{}, ioc.Transient) // v0.1.1,调用函数InitFunc()获取初始化函数来完成初始化
ioc.AddTransient[*Class1](func() *Class1 { // v1.2.0,直接通过传入的函数来完成
var svc Class1
// inject to *struct
ioc.Inject(&svc) // v1.2.0,支持注入到结构体
} // register service to interface.
container.RegisterTo(&Class2{Name: "Jerry Bai"}, (*Interface2)(nil), ioc.Singleton) // v0.1.1
ioc.AddSingleton[Interface2](&Class2{Name: "Jerry Bai"}) // v1.2.0
container.RegisterTo(&Class1{}, (*Interface1)(nil), ioc.Transient) // v0.1.1,调用函数InitFunc()获取初始化函数来完成初始化
ioc.AddTransient[Interface1](func() Interface1 { // v1.2.0,直接通过传入的函数来完成
var svc Class1
// inject to *struct
ioc.Inject(&svc) // v1.2.0,支持注入到结构体
} // inject to function
ioc.Inject(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, resolver ioc.Resolver) { // v1.2.0
println("c1.C2Name=", c1.C2.Name)
println("c2.Name=", c2.Name)
println("i1.GetC2Name=()", i1.GetC2Name())
println("i2.GetName=()", i2.GetName())
})
container.Invoke(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, roContainer ioc.ReadonlyContainer) { // v0.1.1
println("c1.C2Name=", c1.C2Name)
println("c2.Name=", c2.Name)
println("i1.GetC2Name=()", i1.GetC2Name())
println("i2.GetName=()", i2.GetName())
})

  新版本,从功能角度,增加支持了结构体注入、泛型方式获取服务实例、替换已存在的服务。

// get service from ioc(go1.18开始支持泛型)
c1 := ioc.GetService[*Class1]
c2 := ioc.GetService[*Class2]
i1 := ioc.GetService[Interface1]
i2 := ioc.GetService[Interface2]
// override exists service(一般用于覆盖默认注入的对象)
c := ioc.New()
ioc.SetParent(c)
ioc.AddSingletonToC[Interface3](c, &Class3{Name: "Jerry Bai"}) // add service to parent's container
i3 := ioc.GetService[Interface3]() // *Class3, 'Interface3' only exists in parent's container
ioc.AddSingleton[Interface3](&Class4{Name: "Jerry Bai"}) // add service to global's container
i3 = ioc.GetService[Interface3]() // *Class4, 'Interface3' exists in both global and parent's container

  对结构体初始化的函数定义(模拟构造函数),从固定获取函数的接口 interface{InitFunc() interface{}} 改为按函数名获取(默认为 Initialize)。

type Class2 struct {
Name string
resolver ioc.Resolver
} func (c *Class2) Initialize(resolver ioc.Resolver) string {
c.resolver = resolver
return c.Name
} type Class3 struct {
Name string
resolver ioc.Resolver
} // specific custom initialize method name
func (c *Class3) InitializeMethodName() string {
return "MyInitialize"
} // custom initialize method
func (c *Class3) MyInitialize(resolver ioc.Resolver) string {
c.resolver = resolver
return c.Name
}

以下是新版本的性能测试。带 “Native” 的为原生调用,具体测试代码,参见源码:https://github.com/berkaroad/ioc/blob/master/benchmark_test.go

go test -run=none -count=1 -benchtime=1000000x -benchmem -bench=. ./...

goos: linux
goarch: amd64
pkg: github.com/berkaroad/ioc
cpu: AMD Ryzen 7 5800H with Radeon Graphics
BenchmarkGetSingletonService-4 1000000 26.16 ns/op 0 B/op 0 allocs/op
BenchmarkGetTransientService-4 1000000 370.9 ns/op 48 B/op 1 allocs/op
BenchmarkGetTransientServiceNative-4 1000000 131.9 ns/op 48 B/op 1 allocs/op
BenchmarkInjectToFunc-4 1000000 659.5 ns/op 144 B/op 5 allocs/op
BenchmarkInjectToFuncNative-4 1000000 89.26 ns/op 0 B/op 0 allocs/op
BenchmarkInjectToStruct-4 1000000 311.7 ns/op 0 B/op 0 allocs/op
BenchmarkInjectToStructNative-4 1000000 87.64 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/berkaroad/ioc 1.686s

---------------------------------分割线-------------------------------------------------------------

我的ioc项目,已经挂在github上,有兴趣的可以去了解下。https://github.com/berkaroad/ioc

使用中有何问题,欢迎在github上给我提issue,谢谢!

golang 依赖控制反转(IoC) 改进版的更多相关文章

  1. golang 依赖控制反转(IoC)

    主流开发语言,为了达到项目间的低耦合,都会借助IoC框架来实现.即抽象和实现分离,使用抽象层,不用关心这些抽象层的具体实现:抽象层的实现,可以独立实现.现在比较流行的领域驱动设计(ddd),为了达到将 ...

  2. 浅析“依赖注入(DI)/控制反转(IOC)”的实现思路

    开始学习Spring的时候,对依赖注入(DI)——也叫控制反转(IOC)—— 的理解不是很深刻.随着学习的深入,也逐渐有了自己的认识,在此记录,也希望能帮助其他入门同学更深入地理解Spring.本文不 ...

  3. 控制反转IOC的依赖注入方式

    引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...

  4. 控制反转IOC与依赖注入DI

    理解 IOC  http://www.cnblogs.com/zhangchenliang/archive/2013/01/08/2850970.html IOC 相关实例      的http:// ...

  5. 控制反转(Ioc)和依赖注入(DI)

    控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...

  6. 控制反转IOC与依赖注入DI【转】

    转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...

  7. 依赖注入(DI)和控制反转(IOC)

    依赖注入(DI)和控制反转(IOC) 0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只 ...

  8. iOS控制反转(IoC)与依赖注入(DI)的实现

    背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大 ...

  9. 个人对【依赖倒置(DIP)】、【控制反转(IOC)】、【依赖注入(DI)】浅显理解

    一.依赖倒置(Dependency Inversion Principle) 依赖倒置是面向对象设计领域的一种软件设计原则.(其他的设计原则还有:单一职责原则.开放封闭原则.里式替换原则.接口分离原则 ...

  10. 【转载】浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)

    原文地址 http://blog.csdn.net/briblue/article/details/75093382 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来 ...

随机推荐

  1. 扩展说明: 指令微调 Llama 2

    这篇博客是一篇来自 Meta AI,关于指令微调 Llama 2 的扩展说明.旨在聚焦构建指令数据集,有了它,我们则可以使用自己的指令来微调 Llama 2 基础模型. 目标是构建一个能够基于输入内容 ...

  2. CF505C Mr. Kitayuta, the Treasure Hunter

    题目链接 题目 见链接. 题解 知识点:线性dp. 常规的状态 \(dp[i][j]\) 表示为到第 \(i\) 个岛上一步走了 \(j\) 能得到宝藏的最大值,会炸空间.注意到步数是就算从 \(1\ ...

  3. es6 快速入门 系列 —— 解构

    其他章节请看: es6 快速入门 系列 解构 我们经常使用数组或对象存储数据,然后从中提取出相关数据信息 试图解决的问题 以前开发者为了从对象或数组中提取出特定数据并赋值给变量,编写了很多重复的代码, ...

  4. oracle FGAC(细粒度访问控制)介绍

    在ORACLE中,RLS有时也叫做虚拟私有数据库(VPD)或者细粒度访问控制(FGAC). RLS由8i引进,利用这一特性我们可以对表定义安全策略(并且指明对表的操作类型),实现对用户可以看到或者修改 ...

  5. SQL Server使用常见问题

    普通分页查询 三种方式: Top Not IN 方式:查询靠前的数据较快 ROW_NUMBER() OVER()方式:查询靠后的数据速度比上一种较快,在老版本的SQL Server中最常使用 offs ...

  6. 硬件开发笔记(十): 硬件开发基本流程,制作一个USB转RS232的模块(九):创建CH340G/MAX232封装库sop-16并关联原理图元器件

    前言   有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的.为了更好的表述封装设计过程,本文描述了CH340G和MAX232芯片封装 ...

  7. 6大数据类型之间的转换及数据在内存中的缓存机制----day03

    1.自动类型转换 当2个不同类型的数据进行运算的时候,默认向更高精度转换 数据类型精度从低到高:bool  < int < float <complex 1,1强制类型转换 # Nu ...

  8. error接口

    // 实际上它是interface类型,这个类型有一个返回错误信息的单一方法: type error interface{ Error() string } 创建一个error最简单的方法就是调用er ...

  9. 【LeetCode排序专题01】由旋转数组的最小数字引出的关于排序算法的讨论(冒泡排序、二分查找+暴力法)

    旋转数组的最小数字 剑指 Offer 11. 旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一 ...

  10. 第一百零九篇:基本数据类型(String类型)

    好家伙, 本篇内容为<JS高级程序设计>第三章学习笔记   1.String类型 字符串类型是最常用的几个基本类型之一 字符串可以使用双引号,单引号以及反引号(键盘左Tab上面那个)标示 ...