feat: router 包新增 Multistage 多级分类路由器,用于替代原有的 1~3 级路由器

This commit is contained in:
kercylan98 2023-09-12 12:29:14 +08:00
parent 30dbb14add
commit 10cc443b3a
6 changed files with 221 additions and 0 deletions

View File

@ -5,6 +5,8 @@ import (
"reflect"
)
// NewLevel1Router 创建支持一级分类的路由器
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func NewLevel1Router[Route comparable, Handle any]() *Level1Router[Route, Handle] {
return &Level1Router[Route, Handle]{
routes: map[Route]Handle{},
@ -16,6 +18,8 @@ type Level1Router[Route comparable, Handle any] struct {
routes map[Route]Handle
}
// Route 创建路由
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func (slf *Level1Router[Route, Handle]) Route(route Route, handleFunc Handle) {
if reflect.TypeOf(handleFunc).Kind() != reflect.Func {
panic(fmt.Errorf("route[%v] registration failed, handle must be a function type", route))
@ -27,6 +31,8 @@ func (slf *Level1Router[Route, Handle]) Route(route Route, handleFunc Handle) {
slf.routes[route] = handleFunc
}
// Match 匹配路由
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func (slf *Level1Router[Route, Handle]) Match(route Route) Handle {
return slf.routes[route]
}

View File

@ -5,6 +5,8 @@ import (
"reflect"
)
// NewLevel2Router 创建支持二级分类的路由器
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func NewLevel2Router[Route comparable, Handle any]() *Level2Router[Route, Handle] {
return &Level2Router[Route, Handle]{
routes: map[Route]map[Route]Handle{},
@ -16,6 +18,8 @@ type Level2Router[Route comparable, Handle any] struct {
routes map[Route]map[Route]Handle
}
// Route 创建路由
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func (slf *Level2Router[Route, Handle]) Route(topRoute Route, route Route, handleFunc Handle) {
if reflect.TypeOf(handleFunc).Kind() != reflect.Func {
panic(fmt.Errorf("route[%v] registration failed, handle must be a function type", route))
@ -33,6 +37,8 @@ func (slf *Level2Router[Route, Handle]) Route(topRoute Route, route Route, handl
routes[route] = handleFunc
}
// Match 匹配路由
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func (slf *Level2Router[Route, Handle]) Match(topRoute Route, route Route) Handle {
return slf.routes[topRoute][route]
}

View File

@ -5,6 +5,8 @@ import (
"reflect"
)
// NewLevel3Router 创建支持三级分类的路由器
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func NewLevel3Router[Route comparable, Handle any]() *Level3Router[Route, Handle] {
return &Level3Router[Route, Handle]{
routes: map[Route]map[Route]map[Route]Handle{},
@ -12,10 +14,13 @@ func NewLevel3Router[Route comparable, Handle any]() *Level3Router[Route, Handle
}
// Level3Router 支持三级分类的路由器
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
type Level3Router[Route comparable, Handle any] struct {
routes map[Route]map[Route]map[Route]Handle
}
// Route 创建路由
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func (slf *Level3Router[Route, Handle]) Route(topRoute Route, level2Route Route, route Route, handleFunc Handle) {
if reflect.TypeOf(handleFunc).Kind() != reflect.Func {
panic(fmt.Errorf("route[%v] registration failed, handle must be a function type", route))
@ -37,6 +42,8 @@ func (slf *Level3Router[Route, Handle]) Route(topRoute Route, level2Route Route,
level2Routes[route] = handleFunc
}
// Match 匹配路由
// - Deprecated: 从 Minotaur 0.1.7 开始,由于该路由器设计不合理,局限性大,已弃用。建议使用 Multistage 进行代替。
func (slf *Level3Router[Route, Handle]) Match(topRoute Route, level2Route Route, route Route) Handle {
return slf.routes[topRoute][level2Route][route]
}

116
server/router/multistage.go Normal file
View File

@ -0,0 +1,116 @@
package router
import (
"fmt"
"github.com/kercylan98/minotaur/utils/log"
"reflect"
)
// NewMultistage 创建一个支持多级分类的路由器
func NewMultistage[HandleFunc any]() *Multistage[HandleFunc] {
r := &Multistage[HandleFunc]{
routes: make(map[any]HandleFunc),
subs: make(map[any]*Multistage[HandleFunc]),
}
return r
}
// MultistageBind 多级分类路由绑定函数
type MultistageBind[HandleFunc any] func(HandleFunc)
// Bind 将处理函数绑定到预设的路由中
func (slf MultistageBind[HandleFunc]) Bind(handleFunc HandleFunc) {
slf(handleFunc)
}
// Multistage 支持多级分类的路由器
type Multistage[HandleFunc any] struct {
routes map[any]HandleFunc
subs map[any]*Multistage[HandleFunc]
tag any
}
// Register 注册路由是结合 Sub 和 Route 的快捷方式,用于一次性注册多级路由
// - 该函数将返回一个注册函数可通过调用其将路由绑定到特定处理函数例如router.Register("a", "b").Bind(onExec())
func (slf *Multistage[HandleFunc]) Register(routes ...any) MultistageBind[HandleFunc] {
return func(handleFunc HandleFunc) {
router := slf
for i, route := range routes {
if i == len(routes)-1 {
router.Route(route, handleFunc)
} else {
router = router.Sub(route)
}
}
}
}
// Route 为特定路由绑定处理函数,被绑定的处理函数将可以通过 Match 函数进行匹配
func (slf *Multistage[HandleFunc]) Route(route any, handleFunc HandleFunc) {
if reflect.TypeOf(handleFunc).Kind() != reflect.Func {
panic(fmt.Errorf("route[%v] registration failed, handle must be a function type", route))
}
_, exist := slf.routes[route]
if exist {
panic(fmt.Errorf("the route[%v] has already been registered, duplicate registration is not allowed", route))
}
_, exist = slf.subs[route]
if exist {
panic(fmt.Errorf("the route[%v] has already been registered, duplicate registration is not allowed", route))
}
slf.routes[route] = handleFunc
if slf.tag == nil {
log.Info("Router", log.String("Type", "Multistage"), log.String("Route", fmt.Sprintf("%v", route)))
} else {
log.Info("Router", log.String("Type", "Multistage"), log.String("Route", fmt.Sprintf("%v > %v", slf.tag, route)))
}
}
// Match 匹配已绑定处理函数的路由,返回处理函数
// - 如果未找到将会返回空指针
func (slf *Multistage[HandleFunc]) Match(routes ...any) HandleFunc {
if len(routes) == 0 {
panic(fmt.Errorf("the route cannot be empty"))
}
var handleFunc HandleFunc
var exist bool
var router *Multistage[HandleFunc]
for i, route := range routes {
handleFunc, exist = slf.routes[route]
if exist {
return handleFunc
}
router, exist = slf.subs[route]
if !exist {
return handleFunc
}
if i == len(routes)-1 {
return handleFunc
}
return router.Match(routes[i+1:]...)
}
return handleFunc
}
// Sub 获取子路由器
func (slf *Multistage[HandleFunc]) Sub(route any) *Multistage[HandleFunc] {
_, exist := slf.routes[route]
if exist {
panic(fmt.Errorf("the route[%v] has already been registered, cannot be used as a sub-router", route))
}
router, exist := slf.subs[route]
if !exist {
router = NewMultistage[HandleFunc]()
if slf.tag == nil {
router.tag = fmt.Sprintf("%v", route)
} else {
router.tag = fmt.Sprintf("%v > %v", slf.tag, route)
}
slf.subs[route] = router
}
return router
}

View File

@ -0,0 +1,51 @@
package router_test
import "github.com/kercylan98/minotaur/server/router"
func ExampleNewMultistage() {
router.NewMultistage[func()]()
// Output:
}
func ExampleMultistage_Register() {
r := router.NewMultistage[func()]()
r.Register("System", "Network", "Ping")(func() {
// ...
})
// Output:
}
func ExampleMultistage_Sub() {
r := router.NewMultistage[func()]()
r.Sub("System").Route("Heartbeat", func() {
// ...
})
// Output:
}
func ExampleMultistage_Route() {
r := router.NewMultistage[func()]()
r.Route("ServerTime", func() {
// ...
})
// Output:
}
func ExampleMultistage_Match() {
r := router.NewMultistage[func()]()
r.Route("ServerTime", func() {})
r.Register("System", "Network", "Ping").Bind(func() {})
r.Match("ServerTime")()
r.Match("System", "Network", "Ping")()
// Output:
}

View File

@ -0,0 +1,35 @@
package router_test
import (
"fmt"
"github.com/kercylan98/minotaur/server/router"
"testing"
)
func TestMultistage_Match(t *testing.T) {
r := router.NewMultistage[func()]()
r.Sub("System").Route("Heartbeat", func() {
fmt.Println("Heartbeat")
})
r.Route("ServerTime", func() {
fmt.Println("ServerTime")
})
r.Register("System", "Network", "Ping")(func() {
fmt.Println("Ping")
})
r.Register("System", "Network", "Echo").Bind(onEcho)
r.Match("System", "Heartbeat")()
r.Match("ServerTime")()
r.Match("System", "Network", "Ping")()
r.Match("System", "Network", "Echo")()
fmt.Println(r.Match("None") == nil)
}
func onEcho() {
fmt.Println("Echo")
}