feat: router 包新增 Multistage 多级分类路由器,用于替代原有的 1~3 级路由器
This commit is contained in:
parent
30dbb14add
commit
10cc443b3a
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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:
|
||||
}
|
|
@ -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")
|
||||
}
|
Loading…
Reference in New Issue