2013-03-12 76 views
7

为了应对Web应用程序的每个请求,有关模板正常代码是这样的:是否需要将模板放入地图中以便在Go中重用?

t:= template.New("welcome") 
t, _ = t.ParseFiles("welcome.tpl") 
t.Execute(w, data) 

我猜ParseFiles每次花费很多。是否有可能重用该模板?所以我改进这样的:

//templateMap := make(map[string][template]) 
//... 
tplName :="welcome" 
t := templateMap[tplName] 
if t=nil{ 
    t:= template.New(tplName) 
    t, _ = t.ParseFiles("welcome.tpl") 
    templateMap[tplName] = t 
} 

t.Execute(w, data) 

我不知道它是可行或不可行通过将模板导入地图或缓存来提高效率? 我也想知道Execute是线程安全还是不行?

func (t *Template) Execute(wr io.Writer, data interface{}) (err error)

回答

12

模板实际上可以充当模板自身的映射。这是我做的:

我声明一个全局模板变量:

var t = template.New("master") 

我不实际使用的“主”模板,除了为其他模板的容器。

然后,我的应用程序启动时我加载所有的模板:

func init() { 
    _, err := t.ParseGlob("templates/*.html") 
    if err != nil { 
     log.Fatalln("Error loading templates:", err) 
    } 
} 

然后,当我想用​​的模板之一,我问它的名字:

t.ExecuteTemplate(w, "user.html", data) 
+0

有没有一种方便的方法使这种方法适用于使用继承的模板? (例如,哪里有一些模板的基础模板?) – carbocation 2013-04-10 14:54:38

0

从template.go的源代码,执行功能使用锁,我是一个新手,这看起来是线程安全的,但可能不是效率,如果把模板实例地图和尝试重用它,如果您需要服务大量并发请求:

func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { 
     t.nameSpace.mu.Lock() 
     if !t.escaped { 
       if err = escapeTemplates(t, t.Name()); err != nil { 
         t.escaped = true 
       } 
     } 
     t.nameSpace.mu.Unlock() 
     if err != nil { 
       return 
     } 
     return t.text.Execute(wr, data) 
} 
+0

想必贵部分是最后的执行调用。关键部分是对模板进行一次性初始化,所以不应该引起注意。 – 2013-03-12 12:02:50

相关问题