go web框架的路由分析

来源:互联网 发布:软件采购制度 编辑:程序博客网 时间:2024/06/10 05:09

对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 routerimport (    "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 mainimport (    "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"))}
原创粉丝点击