go-gin源码(一)

day_after_day · · 383 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

hello world

使用Gin实现Hello world非常简单,创建一个router,然后使用其Run的方法:

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main(){
    router := gin.Default()

    router.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello World")
    })
    router.Run(":8000")

}
  • Default函数
// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
    debugPrintWARNINGDefault()
    engine := New()
    engine.Use(Logger(), Recovery())
    return engine
}

函数返回一个默认的框架引擎,从函数实现可以看到,首先是一个版本golang版本检查的日志输出(默认函数),接下来创建了一个最简单的引擎, 引擎中注册两个中间件,写标准日志的、panic recover的, 引擎注册的中间件都是 type HandlerFunc func(*Context) 类型,这个点很值得借鉴。

  • 路由
    首先引擎Engine结构定义可以看出它是组合继承了RouterGroup结构,所以引擎对象也同样是一个路由对象
type Engine struct {
    RouterGroup

    // Enables automatic redirection if the current route can't be matched but a
    // handler for the path with (without) the trailing slash exists.
    // For example if /foo/ is requested but a route only exists for /foo, the
    // client is redirected to /foo with http status code 301 for GET requests
    // and 307 for all other request methods.
    RedirectTrailingSlash bool
   ......
}

如上所示,才有了router.GET(...)的成立,下面我们分析路由RouterGroup这个结构即其特性

type RouterGroup struct {
    Handlers HandlersChain
    basePath string
    engine   *Engine
    root     bool
}

如上,RouterGroup仍然可以拥有自己的engine属性,虽然engine组合继承了RouterGroup,还好这个属性是私有的,限制了其使用范围

// GET is a shortcut for router.Handle("GET", path, handle).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
    return group.handle(http.MethodGet, relativePath, handlers)
}

RouterGroup 实现了如下方法 包括常见的get post delete 等

type IRoutes interface {
    Use(...HandlerFunc) IRoutes

    Handle(string, string, ...HandlerFunc) IRoutes
    Any(string, ...HandlerFunc) IRoutes
    GET(string, ...HandlerFunc) IRoutes
    POST(string, ...HandlerFunc) IRoutes
    DELETE(string, ...HandlerFunc) IRoutes
    PATCH(string, ...HandlerFunc) IRoutes
    PUT(string, ...HandlerFunc) IRoutes
    OPTIONS(string, ...HandlerFunc) IRoutes
    HEAD(string, ...HandlerFunc) IRoutes

    StaticFile(string, string) IRoutes
    Static(string, string) IRoutes
    StaticFS(string, http.FileSystem) IRoutes
}

从上面的接口可以看出,路由方法都是由 路径+处理函数 两个参数构成,在执行GET 、POST函数时,其实就是在注册 对应路径应该使用哪个处理函数来处理,经过进一步查看handle方法,框架是以调用方法来组织的 ,一种方法一个root ,root是一个node数组,node数组元素就是具体的路由路径和处理函数,具体结构如下

//路由树
type methodTrees []methodTree
RouterGroup struct {
   ...
    trees            methodTrees
    ...
}

//每个方法的item
type methodTree struct {
    method string
    root   *node
}
//路由映射item
type node struct {
    path      string
    indices   string
    children  []*node
    handlers  HandlersChain
    priority  uint32
    nType     nodeType
    maxParams uint8
    wildChild bool
    fullPath  string
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:day_after_day

查看原文:go-gin源码(一)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

383 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传