web 框架路由的Group实现

package main

import (
    "fmt"
)

type Router struct {
}

func (r *Router) handle(method, pattern string, handlerChain []interface{}) {
    fmt.Println(fmt.Sprintf("[%s] : %s : %v", method, pattern, handlerChain))
}

type Group struct {
    parent  *Group
    befores []interface{}
    pattern string
    router  *Router
}

func newGroup() *Group {
    return &Group{
        parent:  nil,
        befores: make([]interface{}, 0),
        router:  nil,
    }
}

func (g *Group) Before(handlers ...interface{}) {
    g.befores = append(g.befores, handlers...)
}

func (g *Group) Any(pattern string, handlers ...interface{}) {
    g.handle("Any", pattern, handlers)
}

func (g *Group) Get(pattern string, handlers ...interface{}) {
    g.handle("GET", pattern, handlers)
}

func (g *Group) Post(pattern string, handlers ...interface{}) {
    g.handle("POST", pattern, handlers)
}

func (g *Group) Delete(pattern string, handlers ...interface{}) {
    g.handle("DELETE", pattern, handlers)
}

func (g *Group) Put(pattern string, handlers ...interface{}) {
    g.handle("PUT", pattern, handlers)
}

func (g *Group) Patch(pattern string, handlers ...interface{}) {
    g.handle("PATCH", pattern, handlers)
}

func (g *Group) Options(pattern string, handlers ...interface{}) {
    g.handle("OPTIONS", pattern, handlers)
}

func (g *Group) Head(pattern string, handlers ...interface{}) {
    g.handle("HEAD", pattern, handlers)
}

func (g *Group) Trace(pattern string, handlers ...interface{}) {
    g.handle("TRACE", pattern, handlers)
}

func (g *Group) handle(method, pattern string, handlers []interface{}) {
    patternPath := pattern
    handerChain := make([]interface{}, 0)
    handerChain = append(handerChain, handlers...)

    for {
        patternPath = g.pattern + patternPath
        if len(g.befores) > 0 {
            tmpHandlerChain := make([]interface{}, len(g.befores)+len(handerChain))
            copy(tmpHandlerChain, g.befores)
            copy(tmpHandlerChain[len(g.befores):], handerChain)
            handerChain = tmpHandlerChain
        }

        if g.parent != nil {
            g = g.parent
        } else {
            break
        }
    }

    g.router.handle(method, patternPath, handerChain)
}

func (g *Group) Group(pattern string, fn func(*Group)) {
    subGroup := newGroup()
    subGroup.parent = g
    subGroup.pattern = pattern
    subGroup.router = g.router

    fn(subGroup)
}

func (r *Router) Group(pattern string, fn func(*Group)) {
    g := newGroup()
    g.parent = nil
    g.pattern = pattern
    g.router = r

    fn(g)
}

func main() {
    r := new(Router)

    r.Group("/a", func(g *Group) {
        g.Before(100)

        g.Get("/b", 1)
        g.Group("/b1", func(g *Group) {
            g.Before(200, 201)

            g.Get("/c", 2)
            g.Group("/d", func(g *Group) {
                g.Before(300)
                g.Get("/e", 3)
            })
        })
    })
    r.Group("/a1", func(g *Group) {
        g.Get("/1", 1)
    })

}

共 1 个回复


chenhao

最近又更新了一版更好的实现,见water的router.go

# 0