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())
life
life