依赖
总结下先有的获取对象依赖方式
比较原始的New, 全局global保存
基于反射读取对象的依赖, 程序启动时由DI库实例化(代表作dig
等)
基于反射读取对象的依赖, 编译前生成完整构建函数(代表作wire
等)
第一种:最方便, 直接快捷, 大量依赖时候, 但是因为是手动的, 容易出现实例顺序非预期, 不方便自动测试, mock等。
第二种:因为是启动时反射获取依赖的, 需要定义额外的函数给DI系统解析, 例如一个结构的注入必须要要额外的代码, 非常麻烦, 不建议使用
//提供者err:=c.Provide(func(conn*sql.DB)(*UserGateway,*CommentGateway,error){//...})iferr!=nil{//...}//使用者err:=c.Invoke(func(l*log.Logger){//...})iferr!=nil{//...}
第三种, 同样是基于反射, 所以依然需要一个额外函数(只有配置信息)提供反射信息, 生成同名函数, 便捷度基本和手动New一致, wire
由 Google 开源
funcInitializeNewGormProvider()*Gorm{wire.Build(NewGormProvider,InitializeNewConfProvider)returnnil}
我的方案
原理和wire一样, 根据配置信息生成自动构建函数, 但是不基于反射, 因为反射需要程序是完整的, 编译后才读取信息, 相对慢, 需要每个目录改完手动执行wire .
命令(每个目录每次花费1秒等)。
先看一个场景, 数据库服务是依赖配置服务, 从结构体就能看出来, 不需要 func InitializeNewGormProvider() *Gorm{}
函数反射, 未了更加准确(防止注入了不需要的内容)添加一个taginject:""
和@Bean
注解
//@BeantypeGormstruct{conf*Conf`inject:""`}
所以,注入其实是可以直接基于源码的信息都能实现的。
我只要实现一个go
代码解析工具,就能生成和wire
工具生成相同的代码, 因为go源码的关键字和结构实在是太简单了, 没有多少语法糖, 做一下分词
再按语法规则读取源码信息, 工具实现比较容易 。 工具使用php实现( 公司都是mac,php环境mac电脑自带, 方便使用模版生成go代码) https://github.com/go-home-admin/home-toolset-php 重要是php解析很快, 整个项目生成一次都是一秒内
ORM 生成代码
编写工具后, 也可以生成其他辅助代码, 例如原始结构, 添加@Orm后, 自动根据字段信息生成通用代码
//@OrmtypeGormstruct{Iduint32`json:"id"`UserNamestring`json:"user_name"`}
逻辑就可以直接使用
u:=&UsersTable{}data:=u.WhereUserName("test").And(func(table*UsersTable){table.WhereId(1).OrWhereId(2)}).Or(func(table*UsersTable){table.WhereId(2).Or(func(table*UsersTable){table.WhereId(1)})}).Find()//select*formuserswhereuser_name=?and(id=?orid=?)or(id=?or(id=?))utils.Dump(data)
作者:程序狗007著作权归作者所有。