经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
golang 依赖控制反转(IoC) 改进版
来源:cnblogs  作者:Berkaroad  时间:2024/3/20 9:11:43  对本文有异议

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

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

  1. var container = ioc.NewContainer() // v0.1.1
  2. var container = ioc.New() // v1.2.0,非必需,可以直接使用ioc.XXX 即使用内置全局Container
  3. // register service to *struct
  4. container.Register(&Class2{Name: "Jerry Bai"}, ioc.Singleton) // v0.1.1
  5. ioc.AddSingleton[*Class2](&Class2{Name: "Jerry Bai"}) // v1.2.0
  6. container.Register(&Class1{}, ioc.Transient) // v0.1.1,调用函数InitFunc()获取初始化函数来完成初始化
  7. ioc.AddTransient[*Class1](func() *Class1 { // v1.2.0,直接通过传入的函数来完成
  8. var svc Class1
  9. // inject to *struct
  10. ioc.Inject(&svc) // v1.2.0,支持注入到结构体
  11. }
  12. // register service to interface.
  13. container.RegisterTo(&Class2{Name: "Jerry Bai"}, (*Interface2)(nil), ioc.Singleton) // v0.1.1
  14. ioc.AddSingleton[Interface2](&Class2{Name: "Jerry Bai"}) // v1.2.0
  15. container.RegisterTo(&Class1{}, (*Interface1)(nil), ioc.Transient) // v0.1.1,调用函数InitFunc()获取初始化函数来完成初始化
  16. ioc.AddTransient[Interface1](func() Interface1 { // v1.2.0,直接通过传入的函数来完成
  17. var svc Class1
  18. // inject to *struct
  19. ioc.Inject(&svc) // v1.2.0,支持注入到结构体
  20. }
  21. // inject to function
  22. ioc.Inject(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, resolver ioc.Resolver) { // v1.2.0
  23. println("c1.C2Name=", c1.C2.Name)
  24. println("c2.Name=", c2.Name)
  25. println("i1.GetC2Name=()", i1.GetC2Name())
  26. println("i2.GetName=()", i2.GetName())
  27. })
  28. container.Invoke(func(c1 *Class1, c2 *Class2, i1 Interface1, i2 Interface2, roContainer ioc.ReadonlyContainer) { // v0.1.1
  29. println("c1.C2Name=", c1.C2Name)
  30. println("c2.Name=", c2.Name)
  31. println("i1.GetC2Name=()", i1.GetC2Name())
  32. println("i2.GetName=()", i2.GetName())
  33. })

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

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

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

  1. type Class2 struct {
  2. Name string
  3. resolver ioc.Resolver
  4. }
  5. func (c *Class2) Initialize(resolver ioc.Resolver) string {
  6. c.resolver = resolver
  7. return c.Name
  8. }
  9. type Class3 struct {
  10. Name string
  11. resolver ioc.Resolver
  12. }
  13. // specific custom initialize method name
  14. func (c *Class3) InitializeMethodName() string {
  15. return "MyInitialize"
  16. }
  17. // custom initialize method
  18. func (c *Class3) MyInitialize(resolver ioc.Resolver) string {
  19. c.resolver = resolver
  20. return c.Name
  21. }

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

  1. go test -run=none -count=1 -benchtime=1000000x -benchmem -bench=. ./...
  2. goos: linux
  3. goarch: amd64
  4. pkg: github.com/berkaroad/ioc
  5. cpu: AMD Ryzen 7 5800H with Radeon Graphics
  6. BenchmarkGetSingletonService-4 1000000 26.16 ns/op 0 B/op 0 allocs/op
  7. BenchmarkGetTransientService-4 1000000 370.9 ns/op 48 B/op 1 allocs/op
  8. BenchmarkGetTransientServiceNative-4 1000000 131.9 ns/op 48 B/op 1 allocs/op
  9. BenchmarkInjectToFunc-4 1000000 659.5 ns/op 144 B/op 5 allocs/op
  10. BenchmarkInjectToFuncNative-4 1000000 89.26 ns/op 0 B/op 0 allocs/op
  11. BenchmarkInjectToStruct-4 1000000 311.7 ns/op 0 B/op 0 allocs/op
  12. BenchmarkInjectToStructNative-4 1000000 87.64 ns/op 0 B/op 0 allocs/op
  13. PASS
  14. ok github.com/berkaroad/ioc 1.686s

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

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

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

原文链接:https://www.cnblogs.com/Berkaroad/p/18083329/ioc

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号