从零实现gin day06 解析模版

79 阅读2分钟

前言

上一章,我们学习了如何在框架中加入中间件,本章我们要实现解析模版,并且渲染数据到模板中

代码实现

原生代码实现文件服务器

  • 使用 http.FileServer 函数创建了一个文件服务器 server,用于处理对静态文件的请求。这个文件服务器的根目录就是我们之前创建的 dir 对象。
  • 使用 http.StripPrefix 函数去除 URL 前缀,并将剩余的路径传递给文件服务器处理。例如,访问127.0.0.1:8181/static/a.txt 文件服务器处理的就是a.txt 这个文件

dir := http.Dir("./static")  
server := http.FileServer(dir)  
prefix := "/static"  
http.Handle(prefix+"/", http.StripPrefix(prefix, server))  
http.ListenAndServe(":8181", nil)

在框架中使用文件服务器加载文件

  • 创建静态的Handler.这个方法主要是通过http.StripPrefix 用于创建一个带有前缀路径的处理器
  • Static 静态文件服务
func (g *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandleFunc {  
    absolutePath := path.Join(g.prefix, relativePath)  
    server := http.StripPrefix(absolutePath, http.FileServer(fs))  
    return func(ctx *Context) {  
            file := ctx.Param("filepath")  
            if _, err := fs.Open(file); err != nil {  
            ctx.Status(http.StatusNotFound)  
            return  
        }  
        server.ServeHTTP(ctx.Writer, ctx.Req)  
   }  
}  
 
func (g *RouterGroup) Static(relativePath string, root string) {  
    handler := g.createStaticHandler(relativePath, http.Dir(root))  
    urlPatten := path.Join(relativePath, "*filepath")  
    g.GET(urlPatten, handler)  
}

加载模版的方法

  • html/template为 HTML 提供了较为完整的支持。包括普通变量渲染、列表渲染、对象渲染等。框架的模板渲染直接使用了html/template提供的能力。
type Engine struct {  
    *RouterGroup  
    router *Router  
    groups []*RouterGroup  
    httpTemplate *template.Template //将所有的模版加载进内存  
    funcMap template.FuncMap //自定义模版渲染函数  
}  
  
//设置funcmap  
func (e *Engine) SetFuncMap(funcMap template.FuncMap) {  
    e.funcMap = funcMap  
}  
  
//加载HTML模板  
func (e *Engine) LoadHTMLGlob(patten string) {  
    e.httpTemplate = template.Must(template.New("").Funcs(e.funcMap).ParseGlob(patten)) 
}

修改Context和gee

  • 修改HTML,加入name参数可以便于找到需要执行的模版
  • 修改ServeHTTP,给Context赋值engine
func (c *Context) HTML(code int, name string, data interface{}) {  
    c.Status(code)  
    c.SetHeader("Content-Type", "text/html")  
    if err := c.engine.httpTemplate.ExecuteTemplate(c.Writer, name, data); err != nil { 
        c.String(500, "服务器错误:%s", err.Error())  
    }  
}
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {  
    var middlerwares []HandleFunc  
    for _, group := range e.groups {  
        if strings.HasPrefix(r.URL.Path, group.prefix) {  
            middlerwares = append(middlerwares, group.middleware...)  
        }  
    }  
    c := newContext(w, r)  
    c.handlers = middlerwares  
    c.engine = e  
    e.router.Handle(c)  
}

文件架构/测试

image.png

func main() {
    e := newEngine()  
    e.Static("/assets", "./static")  
    e.LoadHTMLGlob("template/*")  

    e.GET("/", func(ctx *Context) {  
        ctx.HTML(http.StatusOK, "b.tmpl", gee.H{  
        "Title": "gin从零开始",  
        "Body": "body",  
        })  
    })  
    e.Run(":7999")
}

image.png