Gin 基础核心源码(一)

本项目源码

gin-copy

简介

  • 本系列将从 Gin 的第一次 git 提交 15216a0 出发,简洁化地将 Gin 的代码进行提取,方便学习以及深入了解 Gin 这个框架

须知

  • Gin 的核心路由使用了 httprouter 包

基础 struct

  • Gin 中将请求,响应等,都进行了 struct 包装

响应 struct

// 核心响应 struct 
// Writer 对 http.ResponseWriter 进行了封装,用以响应数据
// Error 包含了错误信息的收集与存储
// Params httprouter 包中,请求路由的参数
// handlers 中间件实现的关键,本质上是另一个 Content
// index 中间件实现的关键,表示进行到的层次
// engine 服务运行基础引擎
type Content struct {
  Req *http.Request
  Writer ResponseWriter
  Error []ErrorMsg
  Params httprouter.Params
  handlers []HandlerFunc
  engine *Engine
  index int8
}

// 错误信息结构体
type ErrorMsg struct {
  Message string `json:"msg"`    // 信息
  Meta interface{} `json:"meta"` // 元信息
}

// interface 多元化响应信息
type ResponseWriter interface {
  http.ResponseWriter
  Status() int
  Written() bool
}

// 请求处理
type HandlerFunc func(*Content)

引擎 struct

// Engine 引擎
// RouterGroup 路由组!
// router httprouter包的实例
type Engine struct {
  *RouterGroup
  router *httprouter.Router
}

// RouterGroup 路由组
type RouterGroup struct {
  Handlers []HandlerFunc
  prefix string
  parent *RouterGroup
  engine *Engine
}

武装 struct

  • 在基本 stuct 设计完成后,就是要进行方法的增加了

响应

// 写入 Header
func (rw *responseWriter) WriteHeader(s int) {
  rw.ResponseWriter.WriteHeader(s)
  rw.status = s
}
// 书写返回数据
func (rw *responseWriter) Write(b []byte) (int, error) {
  return rw.ResponseWriter.Write(b)
}
// 获取返回状态
func (rw *responseWriter) Status() int {
  return rw.status
}
// 是否完成返回值书写
func (rw *responseWriter) Written() bool {
  return rw.status != 0
}

请求处理

// 获取父路由组可能有的 请求处理(Handle)
func (group *RouterGroup) allHandlers(handlers []HandlerFunc) []HandlerFunc {
   local := append(group.Handlers, handlers...)
   if group.parent != nil {
      return group.parent.allHandlers(local)
   } else {
      return local
   }
}
// for 循环处理每一层的 Handle
func (c *Content) Next() {
   c.index++
   s := int8(len(c.handlers))
   for ; c.index < s; c.index++ {
      c.handlers[c.index](c)
   }
}
// 最基本的响应添加
func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
   p = path.Join(group.prefix, p)
   handlers = group.allHandlers(handlers)
   group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
      group.createContext(w, req, params, handlers).Next()
   })
}
// 创建响应 struct
func (group *RouterGroup) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Content {
   return &Content{
      Req: req,
      Writer: &responseWriter{w, 0},
      index: -1,
      engine: group.engine,
      Params: params,
      handlers: handlers,
   }
}
// Handle 封装
func (group *RouterGroup) GET(path string, handlers ...HandlerFunc) {
   group.Handle("GET", path, handlers)
}
// 返回数据格式封装
func (c *Content) String(code int, msg string) {
   c.Writer.Header().Set("Content-Type", "text/plain")
   c.Writer.WriteHeader(code)
   c.Writer.Write([]byte(msg))
}

引擎启动

  • 将启动方法进行封装
// 创建引擎
func New() *Engine {
   engine := &Engine{}
   engine.RouterGroup = &RouterGroup{nil, "/", nil, engine}
   engine.router = httprouter.New()
   return engine
}
// 默认引擎
func Default() *Engine {
   engine := New()
   return engine
}
// http 响应接口实现
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   engine.router.ServeHTTP(w, req)
}
// 服务启动!
func (engine *Engine) Run(addr string) {
   err := http.ListenAndServe(addr, engine)
   if err != nil {
      fmt.Println(err)
   }
}

基础测试

func main() {
   r := gin_copy.Default()
   r.GET("/ping", func(c * gin_copy.Content) {
      c.String(200, "pong")
   })
   r.Run(":8082")
}

本文作者: 柠檬炸裂
本文链接: https://www.datamac.cn/archives/gin基础核心源码一
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值