Gin框架简洁版

介绍

看完Gin源码后,我在想是否可以尝试自己写一个简单的web-go框架,既能帮助自己更好的理解Gin,又能当做一个测验,检测自己是否真的学会了一些东西。

所以自己做了一个简单版的框架,这个框架包含了一些Gin框架的核心内容,感兴趣的朋友可以先看这个简单版的框架,然后再看我写的gin源码剖析,可能会更加容易理解。

写这个小框架的时候,突然想起了以前看侯捷的深入浅出MFC,有一章的标题叫-MFC六大关键技术之仿真。这个简洁版也算是gin框架的一个仿真吧。

框架写的很简单,主要是为了学习目的,可能有很多的漏洞,如果大家发现的话,可以告诉我进行更改。

代码路径

https://github.com/shidawuhen/asap/tree/feature_pzq_simpleframe

源码

main.go

package main

import (
   _ "asap/docs"
   "fmt"

   f "asap/framework"
)

func ping(c *f.Context) {
   fmt.Println(1)
   c.String("%s", "ping")
}

func main() {
   e := f.New()
   e.AddRoute("GET", "/ping", ping)
   e.Run("127.0.0.1:9090")
}

framework.go

package framework

import (
   "net/http"
   "sync"

   "fmt"
)

type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc

//Context,用于处理请求的输入和输出数据
type Context struct {
   Request *http.Request
   Writer  http.ResponseWriter
}

//将请求返回值写入http.Responsewriter中
func (c *Context) String(format string, data ...interface{}) {
   fmt.Fprintf(c.Writer, format, data...)
   return
}

//核心结构,存放路由规则和使用pool获取与释放Context,减少GC
type Engine struct {
   pool   sync.Pool
   router map[string]map[string]HandlersChain
}

//Engine初始化
func New() *Engine {
   fmt.Println("start")
   engine := &Engine{}
   engine.pool.New = func() interface{} {
      return engine.allocateContext()
   }
   engine.router = make(map[string]map[string]HandlersChain, 0)
   return engine
}

func (engine *Engine) allocateContext() *Context {
   return &Context{}
}

//请求过来时http包会调用该函数
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   c := engine.pool.Get().(*Context)
   //1.context初始化
   c.Writer = w
   c.Request = req
   //2.真正的处理请求逻辑
   engine.handleHTTPRequest(c)

   engine.pool.Put(c)
}

func (engine *Engine) handleHTTPRequest(c *Context) {
   httpMethod := c.Request.Method
   rPath := c.Request.URL.Path
   //从router中找到对应的方法并执行,如果不存在,则直接返回
   routers, ok := engine.router[httpMethod]
   if ok {
      handles, ok := routers[rPath]
      if ok {
         for _, handle := range handles {
            handle(c)
         }
         return
      }
   }
   c.String("%s", httpMethod+" "+rPath+" doesnt exists")
   return
}

//将路由添加到router中,没有并发操作,所以不加锁
func (engine *Engine) AddRoute(method, path string, handlers ...HandlerFunc) {
   //1.判断该http方法是否存在
   _, ok := engine.router[method]
   if !ok {
      engine.router[method] = make(map[string]HandlersChain, 0)
   }
   //2.判断该路径是否存在,如果不存在则插入,如果存在,则不处理
   _, ok = engine.router[method][path]
   if !ok {
      engine.router[method][path] = handlers
   }
}

//运行服务,监听请求
func (engine *Engine) Run(address string) (err error) {
   err = http.ListenAndServe(address, engine)
   return
}

调用关系

这次修改,使得包之间的调用关系很清晰

执行:go-callvis -group pkg,type -ignore fmt,net/http,sync myproject/src

image-20200216115303875.png

image-20200216115509091.png

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

招聘

  1. 字节跳动|抖音电商服务端技术岗位虚位以待
  2. 字节跳动招聘专题

设计模式

  1. Go设计模式(6)-单例模式
  2. Go设计模式(5)-类图符号表示法
  3. Go设计模式(4)-代码编写优化
  4. Go设计模式(4)-代码编写
  5. Go设计模式(3)-设计原则
  6. Go设计模式(2)-面向对象分析与设计
  7. Go设计模式(1)-语法

语言

  1. Go工具之generate
  2. Go单例实现方案
  3. Go通道实现原理
  4. Go定时器实现原理
  5. Beego框架使用
  6. Golang源码BUG追查
  7. Gin框架简洁版
  8. Gin源码剖析

架构

  1. 支付接入常规问题
  2. 限流实现2
  3. 秒杀系统
  4. 分布式系统与一致性协议
  5. 微服务之服务框架和注册中心
  6. 浅谈微服务
  7. 限流实现1
  8. CDN请求过程详解
  9. 常用缓存技巧
  10. 如何高效对接第三方支付
  11. 算法总结

存储

  1. MySQL开发规范
  2. Redis实现分布式锁
  3. 事务原子性、一致性、持久性的实现原理
  4. InnoDB锁与事务简析

网络

  1. HTTP2.0基础教程
  2. HTTPS配置实战
  3. HTTPS连接过程
  4. TCP性能优化

工具

  1. 根据mysql表自动生成go struct
  2. Markdown编辑器推荐-typora

读书笔记

  1. 原则
  2. 资治通鉴
  3. 敏捷革命
  4. 如何锻炼自己的记忆力
  5. 简单的逻辑学-读后感
  6. 热风-读后感
  7. 论语-读后感
  8. 孙子兵法-读后感

思考

  1. 为动员一切力量争取抗战胜利而斗争
  2. 反对自由主义
  3. 实践论
  4. 评价自己的标准
  5. 服务端团队假期值班方案
  6. 项目流程管理
  7. 对项目管理的一些看法
  8. 对产品经理的一些思考
  9. 关于程序员职业发展的思考
  10. 关于代码review的思考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员麻辣烫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值