Gin 使用 radix
tree,尽可能压缩路由的公共前缀,同时使用 indices
加速路由的检索。
radix tree
中间件
使用洋葱型中间件,可以很方便地进行 AOP 编程,有很大的扩展性。
如 Gin 框架中:
1 2 3 4 5
// HandlersChain defines a HandlerFunc slice. type HandlersChain []HandlerFunc
// HandlerFunc defines the handler used by gin middleware as return value. type HandlerFunc func(*Context)
同时为 IRouter 接口也定义 Group
函数,这样可以进一步提升聚合类的逻辑复用:
1 2 3 4 5
// IRouter defines all router handle interface includes single and group router. type IRouter interface { IRoutes Group(string, ...HandlerFunc) *RouterGroup }
// NewInstance is a function that creates a new instance of a service type NewInstance func(...any) (any, error)
// ServiceProvider is an interface that defines a service provider type ServiceProvider interface { // Register a service provider into the container, // whether to initialize the service or not determined by the IsDefer method Register(Container) NewInstance // Boot the service provider, this method will be called after the container is initialized. // Is id recommend to do some initialization work in this method. // If returns error, the service initialization will be failed. Boot(Container) error // IsDefer determines whether the service provider should be deferred. // If true, the service provider will be deferred until the first time the service is used. IsDefer() bool // Params are the parameters which would be passed to the NewInstance function. Params(Container) []any // Name is a method that returns the unique name of the service provider. Name() string }
容器接口定义可参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Container is a service provider container, provides methods to register and resolve service providers. type Container interface { // Bind binds a service provider into the container, // if the service provider is already bound, it would panic. Bind(provider ServiceProvider) error // IsBind checks if a service provider is bound into the container IsBind(key string) bool // Make resolves a service provider from the container Make(key string) (any, error) // MustMake resolves a service provider from the container, if not found, it will panic MustMake(key string) any // MakeNew creates a new instance of a service provider, // it is useful when you need to create a new instance of a service provider // and pass some different parameters to the service provider's constructor. MakeNew(key string, params ...any) (any, error) }
// Helps to check if the Container interface is implemented var _ Container = (*HdwebContainer)(nil)
// HdwebContainer is the default implementation of the Container interface type HdwebContainer struct { // providers is a map of service providers, key is the name of the service provider providers map[string]ServiceProvider // instances is a map of service instances, key is the name of the service instances map[string]any // lock is used to protect the container from concurrent access lock sync.RWMutex }
// NewHdwebContainer creates a new HdwebContainer funcNewHdwebContainer() *HdwebContainer { return &HdwebContainer{ providers: make(map[string]ServiceProvider), instances: make(map[string]any), lock: sync.RWMutex{}, } }
// Bind binds a service provider into the container, // if the service provider is already bound, ' // it will replace the existing one and return an error. func(h *HdwebContainer) Bind(provider ServiceProvider) error { h.lock.Lock() key := provider.Name() if _, ok := h.providers[key]; ok { h.lock.Unlock() panic("service provider already bound: " + key) } h.providers[key] = provider h.lock.Unlock()
h.lock.Lock() defer h.lock.Unlock() if _, ok := h.instances[key]; ok { panic("service provider already resolved: " + key) } h.instances[key] = instance returnnil }
// IsBind checks if a service provider is bound into the container func(h *HdwebContainer) IsBind(key string) bool { return h.findServiceProvider(key) != nil }
// Make resolves a service provider from the container func(h *HdwebContainer) Make(key string) (any, error) { return h.make(key, nil, false) }
// MakeNew creates a new instance of a service provider, // it is useful when you need to create a new instance of a service provider // and pass some different parameters to the service provider's constructor. func(h *HdwebContainer) MakeNew(key string, params ...any) (any, error) { return h.make(key, params, true) }
// MustMake resolves a service provider from the container, if not found, it will panic func(h *HdwebContainer) MustMake(key string) any { ins, err := h.make(key, nil, false) if err != nil { panic(err) } return ins }