Skip to content

Commit

Permalink
feat: 新增 modular 包,用于实现模块化项目
Browse files Browse the repository at this point in the history
  • Loading branch information
kercylan98 committed Jan 30, 2024
1 parent 6b24b7c commit c95b206
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 0 deletions.
5 changes: 5 additions & 0 deletions modular/example/internal/service/expose/attack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package expose

type Attack interface {
Name() string
}
5 changes: 5 additions & 0 deletions modular/example/internal/service/expose/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package expose

type Login interface {
Name() string
}
27 changes: 27 additions & 0 deletions modular/example/internal/service/services/attack/attack.go
Original file line number Diff line number Diff line change
@@ -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
}
27 changes: 27 additions & 0 deletions modular/example/internal/service/services/login/login.go
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions modular/example/main.go
Original file line number Diff line number Diff line change
@@ -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 changes: 69 additions & 0 deletions modular/modular.go
Original file line number Diff line number Diff line change
@@ -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 changes: 36 additions & 0 deletions modular/service.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit c95b206

Please sign in to comment.