go web框架的路由分析

https://github.com/go-chinese-site/go-simple-router.git 项目的代码进行了简单分析

感谢https://studygolang.com/ 有个开源的git项目组
https://github.com/go-chinese-site/

主要是我这种新手学学,高手可以略过。

一直对go的路由很好奇,各种web框架都用到飞起。

go提供了实现了io和并发处理http包,其实做web框架,我们无需对http协议本身处理提供太多东西。

我心中的web框架的工具包一般提供如下:配置读取,db操作,路由,请求封装,session处理

路由是很重要的一块。

go是支持路由重写的 ,只需要实现func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) 接口即可

以下的代码的基础逻辑

Router结构提供了对全局方法和基本路径的封装
route 提供了内部字符串到的处理器的映射。
映射是通过 RouterKey 的 “path-method” 提供的
支持执行一组方法。

Context提供了对http请求的封装。

有一个方法合并的操作
1 把所有的全局方法都合并到注册的方法里面

基本的逻辑
1 注册路由器,在Router里面找到路由器
2 无路由器返回错误处理脚本
3 有路由器,逐步执行

针对group的逻辑最开始是没有读懂的,后来渐渐的明了。

r.Group(“/api”, func() {
r.GET(“/hello”, Hello)
}, GroupHandle)
r.GET(“/1”, Index)
是在注册 r.GET(“/hello”, Hello)的时候先完成把basepath替换成
/api,然后注册 api/hello-get,和里面的方法,然后再改回来。

package router

import (
    "fmt"
    "net/http"
    "path"
)

const (
    // ErrNotFound is not found error.
    ErrNotFound = "not found page"
    // ErrMethodUnsupported is method upsupported error.
    ErrMethodUnsupported = "http method unsupported"
    // RouterKey is route key format.
    RouterKey = "%s-%s"
)

type (
    // Router is a http.Handler. store all routes.
    Router struct {
        // store parent all HandlerFunc.
        globalHandlers []HandlerFunc //存储所有的handlerfunc
        // store parent path.
        basePath string
        // store all routes.
        routers map[string]*route
    }
    // route is storage http method and handle function.
    route struct {
        // http method.
        method string //方法
        // handle function.
        handlers []HandlerFunc //处理器
    }
    // Context is storage request response information.
    Context struct {
        Request *http.Request
        Writer  http.ResponseWriter
        // handle function.
        handlers []HandlerFunc
        // The current handle function index is executed.
        index int8
    }
    //处理器
    // HandlerFunc is a function that can be registered to a route to handle HTTP requests.
    HandlerFunc func(*Context)
)

//初始化
// New is returns an initialized Router.
func New() *Router {
    return &Router{
        routers:  make(map[string]*route),
        basePath: "/",
    }
}

//注册方法
// Use is add global handle function.
func (r *Router) Use(handlers ...HandlerFunc) {
    r.globalHandlers = append(r.globalHandlers, handlers...)
}

//分组路由,设置,执行方法
// Group is add route group.
func (r *Router) Group(partPath string, fn func(), handlers ...HandlerFunc) {
    //得到r的path和handlers
    rootBasePath := r.basePath
    rootHandlers := r.globalHandlers
    //获取所有的handler,和当前路径, 切换root,执行方法或再切换回来
    //先执行的是global方法---当前方法
    r.basePath = path.Join(r.basePath, partPath)
    r.globalHandlers = r.combineHandlers(handlers) //把全局方法加入
    // /api,GroupHandle 放进去
    fn() //这个方法会注册对应的router,和处理器,
    r.basePath = rootBasePath
    r.globalHandlers = rootHandlers
}

// GET is register GET method HandlerFunc to Router.
func (r *Router) GET(partPath string, handlers ...HandlerFunc) {
    path := path.Join(r.basePath, partPath)
    handlers = r.combineHandlers(handlers) //把全局方法加入
    //方法,路径,处理器
    r.addRoute(http.MethodGet, path, handlers)
}

// POST is register POST method HandlerFunc to Router.
func (r *Router) POST(partPath string, handlers ...HandlerFunc) {
    path := path.Join(r.basePath, partPath)
    handlers = r.combineHandlers(handlers)
    //方法,路径,处理器
    r.addRoute(http.MethodPost, path, handlers)
}

// Run listens on the TCP network address addr.
func (r *Router) Run(addr string) error {
    //运行路由
    return http.ListenAndServe(addr, r)
}

//合并处理器方法
// combineHandlers is merge multiple HnalderFunc slice into one HandlerFunc slice.
func (r *Router) combineHandlers(handlers []HandlerFunc) []HandlerFunc {
    finallyLen := len(r.globalHandlers) + len(handlers)
    finallyHandlers := make([]HandlerFunc, finallyLen)
    copy(finallyHandlers, r.globalHandlers)
    copy(finallyHandlers[len(r.globalHandlers):], handlers)
    return finallyHandlers
}

//添加路由
// addRoute is add to routes.
func (r *Router) addRoute(method, path string, handlers []HandlerFunc) {
    route := &route{
        method:   method,
        handlers: handlers,
    }
    r.routers[fmt.Sprintf(RouterKey, path, method)] = route
}

//实现ServeHTTP(w http.ResponseWriter, req *http.Request)
//接口处理器
// ServeHTTP is implement the http.Handler interface.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    //获取方法,路径
    httpMethod := req.Method
    path := req.URL.Path
    //得到对应的路由器
    route, ok := r.routers[fmt.Sprintf(RouterKey, path, httpMethod)]
    //未发现
    if !ok {
        w.WriteHeader(http.StatusNotFound)
        fmt.Fprintf(w, ErrNotFound)
        return
    }
    c := &Context{
        Request:  req,
        Writer:   w,
        handlers: route.handlers, //路由的处理器
        index:    -1,
    }
    c.Next()
}

// Next is call the next handler function.
func (c *Context) Next() {
    c.index++ //下一个方法
    //存在处理器,支持批量运行方法
    if n := int8(len(c.handlers)); c.index < n {
        c.handlers[c.index](c)
    }
}
package main

import (
    "fmt"
    router "github.com/go-chinese-site/go-simple-router"
    "log"
)

// GlobalHandle 全局处理函数
func GlobalHandle(c *router.Context) {
    fmt.Fprint(c.Writer, "begin GlobalHandle!\n")
    c.Next()
    fmt.Fprint(c.Writer, "end GlobalHandle!\n")
}

func Index(c *router.Context) {
    fmt.Fprint(c.Writer, "Welcome!\n")
}

// GroupHandle 分组处理函数
func GroupHandle(c *router.Context) {
    fmt.Fprint(c.Writer, "begin GroupHandle!\n")
    c.Next()
    fmt.Fprint(c.Writer, "end GroupHandle!\n")
}

func Hello(c *router.Context) {
    fmt.Fprint(c.Writer, "hello!\n")
}

func main() {
    r := router.New()
    // 添加全局处理函数
    r.Use(GlobalHandle)

    r.GET("/", Index)

    // 增加路由分组
    r.Group("/api", func() {
        r.GET("/hello", Hello)
    }, GroupHandle)
    r.GET("/1", Index)
    log.Fatal(r.Run(":8080"))
}

猜你喜欢

转载自blog.csdn.net/cabing2005/article/details/78470036