对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"))
}