autodig是基于go-ast的自动生成dig的依赖注入代码的工具。
go get github.com/cindyoshinee/autodig
autodig -scans ./app -output ./app
会在./app下生成autodig.go文件,里面包含所有./app下标记了 //@autodig
的方法/类的相关依赖注入代码
Source Code:
package demo
//@autodig
type Service struct {
Logger string //public字段自动注入
config string //private字段会被忽略
}
//@autodig
func NewLogger() Logger {
return Logger{}
}
Output:
func NewdemoService(Logger string) (*demo.Service, error) {
var autoDigErr error
service := demo.Service{Logger: Logger}
return &service, autoDigErr
}
func demo_NewLogger() demo.Logger {
return demo.NewLogger()
}
func init() {
dep.MustProvide([]interface {
}{NewdemoService, demo_NewLogger})
}
Usage of autodig:
-output string
output file path (default "./app/entrypoint/autodig.go")
-scans string
source code scan dirs, split with ',' (default "./app")
-tag string
tag, only support one, e.g.mock will only generate `//@autodig` or `//@autodig tag:mock` funcs/structs
不传参数默认扫描./app,生成文件为./app/entrypoint/autodig.go
支持在生成struct后自动执行它的init()error方法,用于进行一些初始化工作。e.g. Source Code:
//@autodig
type Service struct {
Logger string
config string
}
func (s *Service) Init() error {
s.config = "{\"Debug\":true}"
return nil
}
Output:
func NewdemoService(Logger string) (*demo.Service, error) {
var autoDigErr error
service := demo.Service{Logger: Logger}
autoDigErr = service.Init() //call init function
return &service, autoDigErr
}
struct默认是注入*Struct,可以通过DigReturn字段指定其他类型。e.g. Source Code:
type ControllerI interface {
}
//@autodig
type ControllerDemo struct {
DigReturn ControllerI
Service *Service
}
Output:
func NewdemoControllerDemo(Service *demo.Service) (demo.ControllerI, error) {
var autoDigErr error
controllerdemo := demo.ControllerDemo{Service: Service, Return: nil}
return &controllerdemo, autoDigErr
}
通过在注释上增加 outgroup:组名 即可指定注入到某个group。 e.g. Source Code:
//@autodig outgroup:restControllers
type ControllerDemo struct {
DigReturn ControllerI
Service *Service
}
//@autodig outgroup:loggers
func NewLogger() Logger {
return Logger{}
}
当需要依赖注入中某个group的所有对象时,给对应field(必须是array)加上tagautodig:"ingroup:组名"
即可。e.g.
Source Code:
//@autodig
type Service struct {
Loggers []Logger `autodig:"ingroup:loggers"`
config string
}
Output:
func NewdemoControllerDemo(Service *demo.Service) (demo.ControllerI, error) {
var autoDigErr error
controllerdemo := demo.ControllerDemo{Service: Service, Return: nil}
return &controllerdemo, autoDigErr
}
func NewdemoService(demoServiceParam struct {
dig.In
Loggers []demo.Logger `group:"loggers"`
}) (*demo.Service, error) {
var autoDigErr error
service := demo.Service{Loggers: demoServiceParam.Loggers}
return &service, autoDigErr
}
func demo_NewLogger() demo.Logger {
return demo.NewLogger()
}
func init() {
dep.MustProvide([]interface {
}{NewdemoControllerDemo}, dig.Group("restControllers"))
dep.MustProvide([]interface {
}{demo_NewLogger}, dig.Group("loggers"))
dep.MustProvide([]interface {
}{NewdemoService})
}
当需要注入多个一样的类时,可以通过指定name来区分。通过在注释/tag上增加 name:名字 即可指定。e.g. Source Code:
//@autodig name:abGrpcClient
func NewAbGrpcClient() *GrpcClient {
return &GrpcClient{}
}
//@autodig
func NewGrpcClient() *GrpcClient {
return &GrpcClient{}
}
//@autodig
type Service struct {
GrpcClient *GrpcClient
AbGrpcClient *GrpcClient `autodig:"name:abGrpcClient"`
}
Output:
func NewdemoService(GrpcClient *GrpcClient, demoServiceParam struct {
dig.In
AbGrpcClient *GrpcClient `name:"abGrpcClient"`
}) (*Service, error) {
var autoDigErr error
service := Service{GrpcClient: GrpcClient, AbGrpcClient: demoServiceParam.AbGrpcClient}
return &service, autoDigErr
}
func init() {
dep.MustProvide([]interface {
}{demo_NewGrpcClient, NewdemoService})
dep.MustProvide([]interface {
}{demo_NewAbGrpcClient}, dig.Name("abGrpcClient"))
}
给@autodig注释增加tag,可以通过命令行的tag指定条件扫描,目前命令行仅支持一个tag,仅支持非关系。// @autodig tag:mock
映射关系:
cmd tag | valid source code |
---|---|
"mock" | "" "mock" |
"!mock" | "" "!mock" "other" |
"" | "" "!mock" |
SourceCode:
//@autodig outgroup:restControllers tag:mock
type ControllerDemo struct {
DigReturn ControllerI
Service *Service
}
//@autodig tag:!mock
type Service struct {
Loggers []Logger `autodig:"ingroup:loggers"`
config string
}
OutPut: cmd empty tag, no Controller
import (
demo "github.com/cindyoshinee/autodig/demo"
dep "github.com/cindyoshinee/autodig/dep"
dig "go.uber.org/dig"
)
func NewdemoService(demoServiceParam struct {
dig.In
Loggers []demo.Logger `group:"loggers"`
}) (*demo.Service, error) {
var autoDigErr error
service := demo.Service{Loggers: demoServiceParam.Loggers}
return &service, autoDigErr
}
func init() {
dep.MustProvide([]interface {
}{NewdemoService})
}
想忽略某些Public Field时,在后面加上tagautodig:"-"
e.g.
Source Code:
//@autodig tag:!mock
type Service struct {
Loggers []Logger `autodig:"-"`
config string
}
OutPut: Loggers be ignored
func NewdemoService() (*demo.Service, error) {
var autoDigErr error
service := demo.Service{}
return &service, autoDigErr
}