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"))}
- go web框架的路由分析
- go 语言的web 框架
- 超全的Go Http路由框架性能比较
- 流行的Go语言web框架简介
- Android路由框架Router的分析
- Go web之旅(路由篇)
- go web开发之url路由设计
- go web: 3 中间件和路由
- Go语言web框架 gin
- Go Web基础--Beego框架
- Faygo一款最适合开发API的 Go Web 框架
- 最好的6个Go语言Web框架
- 最好的6个Go语言Web框架
- 最好的6个Go语言Web框架
- PHP搭建自己的web框架-路由
- Android路由框架Router分析
- Android路由框架Router分析
- nova-api对web请求的路由过程的分析
- Linux系统中rcS文件深入分析
- ionic No provider for Http!
- 数组中两元素的和符合目标
- 为sys/cat文件生成测试签名
- python实现文件夹文件遍历及比对
- go web框架的路由分析
- kudu报错解决
- 关于Struts2的相关知识总结及应用
- selenium-Python之unittest(二)
- ZOJ
- Mongodb的2d查询
- Android多任务切换效果
- HBase源码系列(二)Client如何找到正确的Region Server
- CentOS编译OpenJDK