Rely on
To summarize the previous methods of obtaining object dependencies
- More primitive New, global save
- Based on the dependency of the reflection read object, the program is instantiated by the DI library at startup (magnum opus
dig
Etc.) - Based on the dependency of the reflection read object, the full builder function is generated before compilation (magnum opus
wire
Etc.)
First: the most convenient, direct and fast, a lot of dependencies, but because it is manual, prone to unexpected instance order, inconvenient automatic testing, mock, etc.
The second one is: since the dependency is reflected at startup, additional functions need to be defined for the DI system resolution. For example, the injection of a structure must require additional code, which is very troublesome and is not recommended
/ / provider
err := c.Provide(func(conn *sql.DB) (*UserGateway, *CommentGateway, error) {
// ...
})
iferr ! =nil {
// ...
}
/ / the user
err := c.Invoke(func(l *log.Logger) {
// ...
})
iferr ! =nil {
// ...
}
Copy the code
Third, also based on reflection, so still need an additional function (only configuration information) to provide reflection information, generate the same function, convenient degree and manual New, wire by Google open source
func InitializeNewGormProvider(a) *Gorm {
wire.Build(NewGormProvider, InitializeNewConfProvider)
return nil
}
Copy the code
My plan
The principle is the same as wire, according to the configuration information to generate automatic build function, but not based on reflection, because reflection requires the program is complete, compiled before reading information, relatively slow, need to change each directory to manually execute wire. Command (each directory takes 1 second, etc.).
Look at a scene, database service is dependent on configuration services, from structure can see, don’t need func InitializeNewGormProvider () * Gorm {} function reflection, Add a TagInject :”” and an @bean annotation to be more precise (in case you inject something you don’t need)
// @Bean
type Gorm struct {
conf *Conf `inject:""`
}
Copy the code
So, injection can actually be implemented directly based on the source information.
As long as I realize a go code parsing tool, can generate and WIRE tools generate the same code, because go source key words and structure is too simple, there is no much grammar sugar, do a word segmentation and then according to the grammar rules to read the source information, the tool is easier to achieve. Tools using PHP implementation (the company is MAC, PHP environment MAC computer comes with, easy to use templates to generate go code) github.com/go-home-adm… The important thing is that PHP parsing is fast, and the entire project is generated in less than a second
ORM generates code
After writing the tool, you can also generate additional auxiliary code, such as raw structures, which automatically generate generic code based on field information when you add @ORm
// @Orm
type Gorm struct {
Id uint32 `json:"id"`
UserName string `json:"user_name"`
}
Copy the code
Logic can be used directly
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 * form users where user_name = ? and (id = ? or id = ?) or (id = ? or (id = ?) )
utils.Dump(data)
Copy the code