From 1f46c1d231dfe36543e99d3a28ceb87b0fefae4a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 12:00:43 +0800 Subject: [PATCH 1/3] add template read lock when dev mode --- controller.go | 33 ++++++++++++++++++--------------- template.go | 27 +++++++++++++++++---------- template_test.go | 8 ++++---- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/controller.go b/controller.go index a2943d42..54da81ec 100644 --- a/controller.go +++ b/controller.go @@ -199,6 +199,7 @@ func (c *Controller) RenderString() (string, error) { func (c *Controller) RenderBytes() ([]byte, error) { //if the controller has set layout, then first get the tplname's content set the content to the layout var buf bytes.Buffer + var err error if c.Layout != "" { if c.TplName == "" { c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt @@ -216,13 +217,14 @@ func (c *Controller) RenderBytes() ([]byte, error) { } BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) } - if _, ok := BeeTemplates[c.TplName]; !ok { + if t := getTemplateByName(c.TplName); t == nil { panic("can't find templatefile in the path:" + c.TplName) - } - err := BeeTemplates[c.TplName].ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err + } else { + err = t.ExecuteTemplate(&buf, c.TplName, c.Data) + if err != nil { + Trace("template Execute err:", err) + return nil, err + } } c.Data["LayoutContent"] = template.HTML(buf.String()) @@ -234,7 +236,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - err = BeeTemplates[sectionTpl].ExecuteTemplate(&buf, sectionTpl, c.Data) + err = getTemplateByName(sectionTpl).ExecuteTemplate(&buf, sectionTpl, c.Data) if err != nil { Trace("template Execute err:", err) return nil, err @@ -244,7 +246,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - err = BeeTemplates[c.Layout].ExecuteTemplate(&buf, c.Layout, c.Data) + err = getTemplateByName(c.Layout).ExecuteTemplate(&buf, c.Layout, c.Data) if err != nil { Trace("template Execute err:", err) return nil, err @@ -258,14 +260,15 @@ func (c *Controller) RenderBytes() ([]byte, error) { if BConfig.RunMode == DEV { BuildTemplate(BConfig.WebConfig.ViewsPath, c.TplName) } - if _, ok := BeeTemplates[c.TplName]; !ok { + if t := getTemplateByName(c.TplName); t == nil { panic("can't find templatefile in the path:" + c.TplName) - } - buf.Reset() - err := BeeTemplates[c.TplName].ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err + } else { + buf.Reset() + err = t.ExecuteTemplate(&buf, c.TplName, c.Data) + if err != nil { + Trace("template Execute err:", err) + return nil, err + } } return buf.Bytes(), nil } diff --git a/template.go b/template.go index 9954cf32..da79d383 100644 --- a/template.go +++ b/template.go @@ -30,13 +30,21 @@ import ( var ( beegoTplFuncMap = make(template.FuncMap) - // BeeTemplates caching map and supported template file extensions. - BeeTemplates = make(map[string]*template.Template) - templatesLock sync.Mutex - // BeeTemplateExt stores the template extension which will build - BeeTemplateExt = []string{"tpl", "html"} + // beeTemplates caching map and supported template file extensions. + beeTemplates = make(map[string]*template.Template) + templatesLock sync.RWMutex + // beeTemplateExt stores the template extension which will build + beeTemplateExt = []string{"tpl", "html"} ) +func getTemplateByName(name string) *template.Template { + if BConfig.RunMode == "dev" { + templatesLock.RLock() + defer templatesLock.RUnlock() + } + return beeTemplates[name] +} + func init() { beegoTplFuncMap["dateformat"] = DateFormat beegoTplFuncMap["date"] = Date @@ -55,7 +63,6 @@ func init() { beegoTplFuncMap["config"] = GetConfig beegoTplFuncMap["map_get"] = MapGet - // go1.2 added template funcs // Comparisons beegoTplFuncMap["eq"] = eq // == beegoTplFuncMap["ge"] = ge // >= @@ -103,7 +110,7 @@ func (tf *templateFile) visit(paths string, f os.FileInfo, err error) error { // HasTemplateExt return this path contains supported template extension of beego or not. func HasTemplateExt(paths string) bool { - for _, v := range BeeTemplateExt { + for _, v := range beeTemplateExt { if strings.HasSuffix(paths, "."+v) { return true } @@ -113,12 +120,12 @@ func HasTemplateExt(paths string) bool { // AddTemplateExt add new extension for template. func AddTemplateExt(ext string) { - for _, v := range BeeTemplateExt { + for _, v := range beeTemplateExt { if v == ext { return } } - BeeTemplateExt = append(BeeTemplateExt, ext) + beeTemplateExt = append(beeTemplateExt, ext) } // BuildTemplate will build all template files in a directory. @@ -149,7 +156,7 @@ func BuildTemplate(dir string, files ...string) error { if err != nil { Trace("parse template err:", file, err) } else { - BeeTemplates[file] = t + beeTemplates[file] = t } templatesLock.Unlock() } diff --git a/template_test.go b/template_test.go index 2e222efc..4f13736c 100644 --- a/template_test.go +++ b/template_test.go @@ -70,10 +70,10 @@ func TestTemplate(t *testing.T) { if err := BuildTemplate(dir); err != nil { t.Fatal(err) } - if len(BeeTemplates) != 3 { - t.Fatalf("should be 3 but got %v", len(BeeTemplates)) + if len(beeTemplates) != 3 { + t.Fatalf("should be 3 but got %v", len(beeTemplates)) } - if err := BeeTemplates["index.tpl"].ExecuteTemplate(os.Stdout, "index.tpl", nil); err != nil { + if err := beeTemplates["index.tpl"].ExecuteTemplate(os.Stdout, "index.tpl", nil); err != nil { t.Fatal(err) } for _, name := range files { @@ -126,7 +126,7 @@ func TestRelativeTemplate(t *testing.T) { if err := BuildTemplate(dir, files[1]); err != nil { t.Fatal(err) } - if err := BeeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil { + if err := beeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil { t.Fatal(err) } for _, name := range files { From 6747c55a8115486e6fd7884e4773739cdb402a60 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 12:01:04 +0800 Subject: [PATCH 2/3] remove unused cache --- config.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/config.go b/config.go index 876dbe01..2761e7cb 100644 --- a/config.go +++ b/config.go @@ -16,7 +16,6 @@ package beego import ( "fmt" - "html/template" "os" "path/filepath" "strings" @@ -106,8 +105,6 @@ var ( AppConfig *beegoAppConfig // AppPath is the absolute path to the app AppPath string - // TemplateCache stores template caching - TemplateCache map[string]*template.Template // GlobalSessions is the instance for the session manager GlobalSessions *session.Manager From f5adec31c65f562f8d79871d724bf7a9163173dc Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 14:49:16 +0800 Subject: [PATCH 3/3] improve the template reader function --- controller.go | 68 ++++++++++++++------------------------------------- template.go | 14 ++++++++--- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/controller.go b/controller.go index 54da81ec..372d8c0f 100644 --- a/controller.go +++ b/controller.go @@ -197,35 +197,9 @@ func (c *Controller) RenderString() (string, error) { // RenderBytes returns the bytes of rendered template string. Do not send out response. func (c *Controller) RenderBytes() ([]byte, error) { - //if the controller has set layout, then first get the tplname's content set the content to the layout - var buf bytes.Buffer - var err error - if c.Layout != "" { - if c.TplName == "" { - c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt - } - - if BConfig.RunMode == DEV { - buildFiles := []string{c.TplName} - if c.LayoutSections != nil { - for _, sectionTpl := range c.LayoutSections { - if sectionTpl == "" { - continue - } - buildFiles = append(buildFiles, sectionTpl) - } - } - BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) - } - if t := getTemplateByName(c.TplName); t == nil { - panic("can't find templatefile in the path:" + c.TplName) - } else { - err = t.ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err - } - } + buf, err := c.renderTemplate() + //if the controller has set layout, then first get the tplName's content set the content to the layout + if err == nil && c.Layout != "" { c.Data["LayoutContent"] = template.HTML(buf.String()) if c.LayoutSections != nil { @@ -234,11 +208,9 @@ func (c *Controller) RenderBytes() ([]byte, error) { c.Data[sectionName] = "" continue } - buf.Reset() - err = getTemplateByName(sectionTpl).ExecuteTemplate(&buf, sectionTpl, c.Data) + err = executeTemplate(&buf, sectionTpl, c.Data) if err != nil { - Trace("template Execute err:", err) return nil, err } c.Data[sectionName] = template.HTML(buf.String()) @@ -246,31 +218,29 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - err = getTemplateByName(c.Layout).ExecuteTemplate(&buf, c.Layout, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err - } - return buf.Bytes(), nil + executeTemplate(&buf, c.Layout, c.Data) } + return buf.Bytes(), err +} +func (c *Controller) renderTemplate() (bytes.Buffer, error) { + var buf bytes.Buffer if c.TplName == "" { c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt } if BConfig.RunMode == DEV { - BuildTemplate(BConfig.WebConfig.ViewsPath, c.TplName) - } - if t := getTemplateByName(c.TplName); t == nil { - panic("can't find templatefile in the path:" + c.TplName) - } else { - buf.Reset() - err = t.ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err + buildFiles := []string{c.TplName} + if c.Layout != "" && c.LayoutSections != nil { + for _, sectionTpl := range c.LayoutSections { + if sectionTpl == "" { + continue + } + buildFiles = append(buildFiles, sectionTpl) + } } + BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) } - return buf.Bytes(), nil + return buf, executeTemplate(&buf, c.TplName, c.Data) } // Redirect sends the redirection response to url with status code. diff --git a/template.go b/template.go index da79d383..e6c43f87 100644 --- a/template.go +++ b/template.go @@ -18,6 +18,7 @@ import ( "errors" "fmt" "html/template" + "io" "io/ioutil" "os" "path/filepath" @@ -37,12 +38,19 @@ var ( beeTemplateExt = []string{"tpl", "html"} ) -func getTemplateByName(name string) *template.Template { - if BConfig.RunMode == "dev" { +func executeTemplate(wr io.Writer, name string, data interface{}) error { + if BConfig.RunMode == DEV { templatesLock.RLock() defer templatesLock.RUnlock() } - return beeTemplates[name] + if t, ok := beeTemplates[name]; ok { + err := t.ExecuteTemplate(wr, name, data) + if err != nil { + Trace("template Execute err:", err) + } + return err + } + panic("can't find templatefile in the path:" + name) } func init() {