首页 > 解决方案 > 自定义功能在模板中不起作用

问题描述

我有以下工作正常的操场

package main

import (
    "html/template"
    "os"
)

func main() {
    tmpl := `
{{ $slice := mkSlice "a" 5 "b" }}
{{ range $slice }}
     {{ . }}
{{ end }}
`
    funcMap := map[string]interface{}{"mkSlice": mkSlice}
    t := template.New("").Funcs(template.FuncMap(funcMap))
    template.Must(t.Parse(tmpl))
    t.Execute(os.Stdout, nil)
}

func mkSlice(args ...interface{}) []interface{} {
    return args
}

但是一旦我尝试从模板文件运行,什么都没有显示,也没有收到错误!

func mkSlice(args ...interface{}) []interface{} { // to ceate the array in the template
    return args
}

funcMap := map[string]interface{}{"mkSlice": mkSlice}
tmpl := template.New("").Funcs(template.FuncMap(funcMap))
template.Must(tmpl.ParseFiles("index.html"))
tmpl.Execute(w, nil)

并且index.html是:

{{ $slice := mkSlice "a" 5 "b" }}
{{ range $slice }}
    <span> {{ . }} </span>
{{ end }}

任何想法?

标签: gogo-templates

解决方案


您看不到任何错误,因为您没有检查tmpl.Execute(w, nil). 何时检查:

if err := t.Execute(os.Stdout, nil); err != nil {
    panic(err)
}

您将看到如下输出:

panic: template: "" is an incomplete or empty template

不同之处在于,在第一种情况下,您使用了Template.Parse()以下方法:

... 将文本解析为 t 的模板主体。

请注意,您解析的模板文本将用于t其自身!

在第二种情况下,您使用Template.ParseFiles()了 which:

... 解析命名文件并将生成的模板与 t 相关联。如果发生错误,则停止解析,返回的模板为 nil;否则为 t。必须至少有一个文件。由于 ParseFiles 创建的模板由参数文件的基本名称命名,因此 t 通常应该具有文件的(基本)名称之一的名称。

因此,在您的第一个示例t中包含一个模板,并且该单个模板将由Template.Execute().

在您的第二个示例t中,包含多个关联模板,t它们本身是一个空模板,另一个关联模板名为index.html. 您可以使用以下命令执行该模板Template.ExecuteTemplate()

if err := t.ExecuteTemplate(os.Stdout, "index.html", nil); err != nil {
    panic(err)
}

有关更多信息,请参阅:

去模板名称

Go Template ParseFiles 函数解析多个文件


推荐阅读