教你如何搭建自己的go-gin框架(二) 封装Context

18211167516 · · 132 次点击 · · 开始浏览    
## 引言 > 简单说下本章的重点 * 1、抽离路由 * 2、将writer和request封装成Context,以方便后续扩展,封装了返回类型 * 3、优化框架源码,抽离封装了handleHTTPRequest方法 * 4、[代码地址 https://github.com/18211167516/go-Ebb/tree/master/day2-context](https://github.com/18211167516/go-Ebb/tree/master/day2-context) ## 抽离路由 * 新建router.go ```golang package ebb type router struct{ handlers map[string]HandlerFunc } func newRouter() *router{ return &router{handlers:make(map[string]HandlerFunc)} } func (r *router) addRoute(method string,pattern string,handler HandlerFunc){ key := method+"-"+pattern r.handlers[key] = handler } ``` > 设计Context的必要性 * 对外接口简化调用 (封装了writer和request) * 提供了扩展性(比如支持动态参数、支持中间件等等) ```golang package ebb import ( "net/http" "fmt" "encoding/json" ) type H map[string]interface{} type Context struct{ //write and request Writer http.ResponseWriter Request *http.Request //request info Method string Path string //response HttpCode int } func newContext(w http.ResponseWriter,r *http.Request) *Context{ context := &Context{ Writer:w, Request:r, Path: r.URL.Path, Method: r.Method, } return context } func (c *Context) PostForm(key string) string { return c.Request.FormValue(key) } func (c *Context) Query(key string) string { return c.Request.URL.Query().Get(key) } func (c *Context) Status(code int) { c.HttpCode = code c.Writer.WriteHeader(code) } func (c *Context) SetHeader(key string, value string) { c.Writer.Header().Set(key, value) } func (c *Context) Write(data []byte){ c.Writer.Write(data) } func (c *Context) String(code int,message string,v ...interface{}){ c.SetHeader("Content-Type", "text/plain") c.Status(code) c.Write([]byte(fmt.Sprintf(message, v...))) } func (c *Context) JSON(code int, obj interface{}) { c.SetHeader("Content-Type", "application/json") c.Status(code) data,err:= json.Marshal(obj) if err!=nil { http.Error(c.Writer, err.Error(), 500) } c.Write(data) } func (c *Context) HTML(code int,html string){ c.SetHeader("Content-Type", "text/html") c.Status(code) c.Write([]byte(html)) } ``` * 修改ebb.go ```golang package ebb import ( "net/http" ) //重新定义框架请求处理方法 type HandlerFunc func(*Context) //核心结构体 type Engine struct{ router *router } //实例化结构体 func New() *Engine{ engine := &Engine{ router : newRouter(), } return engine } //添加到结构体路由 func (engine *Engine) addRoute(mothod string,pattern string,handler HandlerFunc){ engine.router.addRoute(mothod,pattern,handler) } func (engine *Engine) GET(pattern string,handler HandlerFunc){ engine.addRoute("GET",pattern,handler) } func (engine *Engine) POST(pattern string,handler HandlerFunc){ engine.addRoute("POST",pattern,handler) } //启动服务 func (engine *Engine) Run(addr string) (err error){ return http.ListenAndServe(addr,engine) } //engine 实现ServeHTTP接口(所有的请求都会走到这) //查找是否路由映射表存在,如果存在则调用,否则返回404 func (engine *Engine) ServeHTTP(w http.ResponseWriter,req *http.Request){ c := newContext(w, req) engine.handleHTTPRequest(c) } //v2 新增 func (engine *Engine) handleHTTPRequest(c *Context){ key := c.Method + "-" + c.Path if handler, ok := engine.router.handlers[key]; ok { handler(c) } else { c.String(http.StatusNotFound, "404 NOT FOUND: %s\n", c.Path) } } ``` > 入口文件应用 ```golang package main import ( "ebb" ) func main(){ r := ebb.New() r.GET("/", func(c *ebb.Context) { c.HTML(200, "<h1>Hello ebb</h1>") }) r.GET("/hello", func(c *ebb.Context) { c.String(200, "hello %s, you from %s\n", c.Query("name"), c.Path) }) r.POST("/login", func(c *ebb.Context) { c.JSON(200, ebb.H{ "name": c.PostForm("name"), }) }) r.Run(":8080") } ```

有疑问加站长微信联系

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

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