我有以下代码:
t, err := template.New("template").Funcs(funcMap).Parse("Howdy {{ myfunc . }}")
在这种形式下一切正常。但是,如果我对ParseFiles执行完全相同的操作,将上面的文本放在template.html
中就不行了:
t, err := template.New("template").Funcs(funcMap).ParseFiles("template.html")
我能够让ParseFiles以下面的形式工作,但无法使Funcs生效:
t, err := template.ParseFiles("template.html")
t.Funcs(funcMap)
当然,最后一种形式是直接调用函数而不是调用接收方法,所以不一样。
任何人都有任何想法在这里发生了什么?很难在模板中找到很多细节。
答案 0 :(得分:1)
try this:
var templates = template.Must(template.New("").Funcs(fmap).ParseFiles("1.tmpl, "2.tmpl"))
答案 1 :(得分:0)
ParseFiles
应该有一些模板的名称,这是filename的基本名称。但是你打电话给template.New
,它会创建一个名为error
的新模板。所以你应该选择一个模板。
package main
import (
"text/template"
"log"
"os"
"strings"
)
func main() {
tmpl, err := template.New("error").Funcs(template.FuncMap{
"trim": strings.TrimSpace,
}).ParseFiles("foo.tmpl")
if err != nil {
log.Fatal(err)
}
tmpl = tmpl.Lookup("foo.tmpl")
err = tmpl.Execute(os.Stdout, " string contains spaces both ")
if err != nil {
log.Fatal(err)
}
}
{{. | trim}}
答案 2 :(得分:0)
进行了一些挖掘并在源代码中找到了template.ParseFiles
的评论:
如果尚未定义,则第一个模板将成为返回值,并且我们将该模板用于后续的新调用以将所有模板关联在一起。此外,如果此文件与t同名,则此文件将成为t的内容,因此t,err:= New(name).Funcs(xxx).ParseFiles(name)有效。否则,我们会创建一个与t。
相关联的新模板
所以格式应该如下,给出我上面的例子:
t, err := template.New("template.html").Funcs(funcMap).ParseFiles("path/template.html")
.New("template.html")
创建一个具有给定名称的空模板,.Funcs(funcMap)
关联我们要应用于模板的任何自定义函数,然后.ParseFiles("path/template.html")
解析一个或多个模板,并且知道这些功能并将内容与该名称的模板相关联。
请注意,第一个文件的基本名称必须与New
中使用的名称相同。解析的任何内容都将与系列中第一个文件具有相同基本名称的空预先存在的模板或具有该基本名称的新模板相关联。
因此,在上面的示例中,创建了一个名为“template”的空模板,并具有与之关联的功能图。然后创建了一个名为“template.html”的新模板。 这些不是相同的!由于ParseFiles
被称为最后一次,t
最终成为“template.html”模板,没有附加任何功能。
最后一个例子怎么样?为什么这不起作用? template.ParseFiles调用接收方法Parse,后者又应用以前注册的任何函数:
trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
这意味着必须在解析之前注册自定义函数。解析模板后添加函数没有任何影响,在尝试调用自定义函数时,在运行时导致nil指针错误。
所以我认为这涵盖了我原来的问题。这里的设计似乎有点笨重。没有意义的是,我可以将ParseFiles
链接到一个模板,并最终返回与我正在链接的模板不同的模板,如果它们的名称不相同。这是违反直觉的,可能应该在未来的版本中解决,以避免混淆。