golang注入框架fx的原理浅谈

uber的fx依赖注入框架:

fx能干啥? 下面睁大氪金x眼:
在这里插入图片描述

没有依赖注入框架时写代码:

直白一点的例子:func1()依赖A模块(假设是DB模块),A依赖B模块(假设是网络模块),B依赖C模块(假设是日志模块),如果没有注入框架的话,程序员需要用代码去确保:

先启动C模块,再启动B模块,再启动A模块,再启动func1。 如果函数组件 和 依赖的模块数量比较庞大的话,就很恶心人了。每次修改一点点与模块相关的代码,你都可能不得不再用大量的时间去调整启动顺序。 贼恶心!!!!!!

因此依赖注入的引入可以减少维护依赖关系的精力,专心使开发人员投入到业务开发中来。

有依赖注入框架时写代码:

Golang没有Java那种生态很全的框架,导致Golang中的init被滥用。但是Golang社区有很多提供依赖注入(DI)的框架,比如:

"github.com/facebookgo/inject"
"go.uber.org/fx"
"go.uber.org/dig"

fx用法示例:

    app := fx.New(

            // 一系列构造函数
            fx.Provide(
                    NewMyConstruct,
                    NewHandler,
                    NewMux,
                    NewLogger,
            ), 
    
            // 构造函数执行完后,执行初始化函数
            fx.Invoke(invokeNothingUse, invokeRegister, invokeAnotherFunc, invokeUseMyconstruct, invokeNothingUse),
    )
        
	// 这里会依次调用fx.Invoke()注册的函数, fx在调用组件入口时,发现过需要参数,就去fx.Provide()注册的构造函数去创建
	// 函数有顺序,有手柄,有参数实体,函数就可以启动起来。
	// 带来的好处是:有的组件可能需要很多不同的构造函数,fx自动取按照顺序创建并初始化。 不需要人为去调整,这样节省了程序员的时间。
    if err := app.Start(startCtx); err != nil {
			log.Fatal(err)  
    } 

Lotus引入fx依赖注入框架,解决的问题:讲各个子模块例如rpc、db、http、libp2p、各种配置参数、随机数、等几百个组件的构造函数用fx.Provide()注册一下先(写入一个容器中,里面有一个map[key]:key是构造函数返回对象的reflect.Type反射类型,val是构造函数(New_XXX_type()) )。

然后通过fx.Invoke()接口,注册各个组件的入口函数。

我总结fx依赖注入框架干的事情主要有3件:

  • 提前声明好函数列表里面的函数在调用时,所传入的参数的来源,临时创建:A参数用funcA()创建,B参数用funcB()创建

  • 按照顺序,声明需要调用的函数列表

    扫描二维码关注公众号,回复: 13306148 查看本文章
  • 在app := fx.New() app.Start(ctx)时,依次执行函数列表,遇到需要参数的函数时,就自动推导依赖关系(遍历查表),然后创建参数,然后去执行

猜你喜欢

转载自blog.csdn.net/jacky128256/article/details/121106691
FX