feat: 新增 modular 包,用于实现模块化项目

This commit is contained in:
kercylan98 2024-01-30 14:22:26 +08:00
parent 6b24b7c576
commit c95b206592
7 changed files with 184 additions and 0 deletions

View File

@ -0,0 +1,5 @@
package expose
type Attack interface {
Name() string
}

View File

@ -0,0 +1,5 @@
package expose
type Login interface {
Name() string
}

View File

@ -0,0 +1,27 @@
package attack
import (
"fmt"
"github.com/kercylan98/minotaur/modular/example/internal/service/expose"
)
type Service struct {
Login expose.Login
name string
}
func (a *Service) OnInit() {
a.name = "attack"
}
func (a *Service) OnPreload() {
fmt.Println(a.name, "call", a.Login.Name())
}
func (a *Service) OnMount() {
}
func (a *Service) Name() string {
return a.name
}

View File

@ -0,0 +1,27 @@
package login
import (
"fmt"
"github.com/kercylan98/minotaur/modular/example/internal/service/expose"
)
type Service struct {
Attack expose.Attack
name string
}
func (l *Service) OnInit() {
l.name = "login"
}
func (l *Service) OnPreload() {
fmt.Println(l.name, "call", l.Attack.Name())
}
func (l *Service) OnMount() {
}
func (l *Service) Name() string {
return l.name
}

15
modular/example/main.go Normal file
View File

@ -0,0 +1,15 @@
package main
import (
"github.com/kercylan98/minotaur/modular"
"github.com/kercylan98/minotaur/modular/example/internal/service/services/attack"
"github.com/kercylan98/minotaur/modular/example/internal/service/services/login"
)
func main() {
modular.RegisterServices(
new(attack.Service),
new(login.Service),
)
modular.Run()
}

69
modular/modular.go Normal file
View File

@ -0,0 +1,69 @@
package modular
import (
"fmt"
"github.com/kercylan98/minotaur/utils/log"
"reflect"
)
var application *modular
func init() {
application = &modular{}
}
type modular struct {
registerServices []Service
services []*service
}
// RegisterServices 注册服务
func (m *modular) RegisterServices(s ...Service) {
application.registerServices = append(application.registerServices, s...)
}
// Run 运行模块化应用程序
func Run() {
m := application
var names = make(map[string]bool)
var tvm = make(map[reflect.Type]reflect.Value)
for i := 0; i < len(m.registerServices); i++ {
s := newService(m.registerServices[i])
if names[s.name] {
panic(fmt.Errorf("service %s is already registered", s.name))
}
names[s.name] = true
tvm[s.vof.Type()] = s.vof
m.services = append(m.services, s)
}
// OnInit
for i := 0; i < len(m.services); i++ {
s := m.services[i]
s.instance.OnInit()
log.Info(fmt.Sprintf("service %s initialized", s.name))
}
// OnPreload
for i := 0; i < len(m.services); i++ {
s := m.services[i]
for f := 0; f < s.vof.Elem().NumField(); f++ {
field := s.vof.Elem().Field(f)
for _, v := range tvm {
if v.Type().AssignableTo(field.Type()) {
field.Set(v)
break
}
}
}
s.instance.OnPreload()
log.Info(fmt.Sprintf("service %s preloaded", s.name))
}
// OnMount
for i := 0; i < len(m.services); i++ {
s := m.services[i]
s.instance.OnMount()
log.Info(fmt.Sprintf("service %s mounted", s.name))
}
}

36
modular/service.go Normal file
View File

@ -0,0 +1,36 @@
package modular
import "reflect"
// Service 模块化服务接口,所有的服务均需要实现该接口,在服务的生命周期内发生任何错误均应通过 panic 阻止服务继续运行
// - 生命周期示例: OnInit -> OnPreload -> OnMount
type Service interface {
// OnInit 服务初始化阶段,该阶段不应该依赖其他任何服务
OnInit()
// OnPreload 预加载阶段,在进入该阶段时,所有服务已经初始化完成,可在该阶段注入其他服务的依赖
OnPreload()
// OnMount 挂载阶段,该阶段所有服务本身及依赖的服务都已经初始化完成,可在该阶段进行服务功能的定义
OnMount()
}
// RegisterServices 注册服务
func RegisterServices(s ...Service) {
application.RegisterServices(s...)
}
func newService(instance Service) *service {
vof := reflect.ValueOf(instance)
return &service{
name: vof.Type().String(),
instance: instance,
vof: vof,
}
}
type service struct {
name string
instance Service
vof reflect.Value
}