Gin框架简洁版

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

## 介绍 看完Gin源码后,我在想是否可以尝试自己写一个简单的web-go框架,既能帮助自己更好的理解Gin,又能当做一个测验,检测自己是否真的学会了一些东西。 所以自己做了一个简单版的框架,这个框架包含了一些Gin框架的核心内容,感兴趣的朋友可以先看这个简单版的框架,然后再看我写的[gin源码剖析](https://studygolang.com/articles/28836),可能会更加容易理解。 写这个小框架的时候,突然想起了以前看侯捷的深入浅出MFC,有一章的标题叫-MFC六大关键技术之仿真。这个简洁版也算是gin框架的一个仿真吧。 框架写的很简单,主要是为了学习目的,可能有很多的漏洞,如果大家发现的话,可以告诉我进行更改。 ## 代码路径 https://github.com/shidawuhen/asap/tree/feature_pzq_simpleframe ## 源码 main.go ```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 ```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 <img src="https://static.studygolang.com/200524/6c12d0257c4b4f2858546f1ff3cb79b0.png" alt="image-20200216115509091" style="zoom:40%;" /> <img src="https://static.studygolang.com/200524/d78b63dff8549c1b9a3b40da03448053.png" alt="image-20200216115509091" style="zoom:40%;" /> ## 最后 大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫) ![qrcode_for_gh_7d704fb87cd1_258.jpg](https://static.studygolang.com/200524/3f0fb1db65ef47c459b6fc1fea280d4a.jpg)

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

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

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