controller执行后
c.RenderArgs["tagsJson"] = c.Json(tagService.GetTags(c.GetUserId())) return c.RenderTemplate("note/note-dev.html")
Controller:
type Controller struct {
RenderArgs map[string]interface{} // Args passed to the template. }
返回 RenderTemplateResult 对象
func (c *Controller) RenderTemplate(templatePath string) Result { // Get the Template.
// 返回 GoTemplate{tmpl, loader} template, err := MainTemplateLoader.Template(templatePath) if err != nil { return c.RenderError(err) } return &RenderTemplateResult{ Template: template, RenderArgs: c.RenderArgs, // 把args给它 } }
result.go
// Action methods return this result to request a template be rendered. type RenderTemplateResult struct { Template Template RenderArgs map[string]interface{} }
// 模仿这个方法
func (r *RenderTemplateResult) render(req *Request, resp *Response, wr io.Writer) { // 这里调用之
err := r.Template.Render(wr, r.RenderArgs) if err == nil { return }
//....
}
func (r *RenderTemplateResult) Apply(req *Request, resp *Response) { // Handle panics when rendering templates. defer func() { if err := recover(); err != nil { ERROR.Println(err) PlaintextErrorResult{fmt.Errorf("Template Execution Panic in %s:\n%s", r.Template.Name(), err)}.Apply(req, resp) } }() chunked := Config.BoolDefault("results.chunked", false) // If it's a HEAD request, throw away the bytes. out := io.Writer(resp.Out) if req.Method == "HEAD" { out = ioutil.Discard } // In a prod mode, write the status, render, and hope for the best. // (In a dev mode, always render to a temporary buffer first to avoid having // error pages distorted by HTML already written) if chunked && !DevMode { resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8") r.render(req, resp, out) // 这里!!! return } // Render the template into a temporary buffer, to see if there was an error // rendering the template. If not, then copy it into the response buffer. // Otherwise, template render errors may result in unpredictable HTML (and // would carry a 200 status code) var b bytes.Buffer r.render(req, resp, &b) if !chunked { resp.Out.Header().Set("Content-Length", strconv.Itoa(b.Len())) } resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8") b.WriteTo(out) }
revel / template.go 里有 MainTemplateLoader 类, Template类, 里面还有自定义模板函数
type Template interface { Name() string Content() []string Render(wr io.Writer, arg interface{}) error }
// Adapter for Go Templates. type GoTemplate strucst { *template.Template loader *TemplateLoader }
// return a 'revel.Template' from Go's template. func (gotmpl GoTemplate) Render(wr io.Writer, arg interface{}) error { return gotmpl.Execute(wr, arg) }
---------------
OK,
tpl := c.RenderTemplate("note/note-dev.html")
// 定义一个io.Writer, 可以是stringIoWriter? 写到string中
var b bytes.Buffer
tpl.Template.Render(b, tpl.RenderArgs)
fmt.Println(b.String())