我目前将我所有的html文件都放在一个平面目录templates/
中,并使用以下方式加载所有内容
tmpl := template.Must(template.ParseGlob("templates/*.html"))
但是我现在想引入一些结构并将模板放入文件夹components
,base
等中。但是当我这样做时,我的网站将停止工作。我认为可能是上述情况,还是我需要引用模板中的路径?
示例
{{ template "navbar" }}
将成为
{{ template "components/navbar" }}
有点困惑...
我现在还使用本机go库而不是框架。
Go的glob不支持子目录中的匹配文件,即不支持**
。
您可以使用第三方库(在github上有很多实现),也可以为子目录的每个“级别”调用filepath.Glob
并将返回的文件名聚集到单个切片中,然后传递切片到template.ParseFiles
:
dirs := []string{
"templates/*.html",
"templates/*/*.html",
"templates/*/*/*.html",
// ...
}
files := []string{}
for _, dir := range dirs {
ff, err := filepath.Glob(dir)
if err != nil {
panic(err)
}
files = append(files, ff)
}
t, err := template.ParseFiles(files...)
if err != nil {
panic(err)
}
// ...
您还需要牢记ParseFiles
的工作方式:(强调我的意思)
ParseFiles创建一个新的模板并解析模板定义从命名文件中。返回的模板名称将具有第一个文件的(基本)名称和(解析的)内容。一定有至少一个文件。如果发生错误,解析将停止并返回*模板为零。
解析多个不同名称的文件目录,最后提到的将是结果目录。对于实例,ParseFiles(“ a / foo”,“ b / foo”)将“ b / foo”存储为模板名为“ foo”,而“ a / foo”不可用。
这意味着,如果要加载所有文件,则必须至少确保以下两项:(1)每个文件的base名称在所有模板文件中都是唯一的,而不仅仅是目录中的(2)通过使用文件内容顶部的ParseFiles
操作为每个文件提供唯一的模板名称(并且不要忘记{{ define "<template_name>" }}
关闭{{ end }}
操作)。
作为第二种方法的示例,假设您的模板中有两个具有相同基本名称的文件,例如define
和templates/foo/header.html
及其内容如下:
templates/bar/header.html
templates/foo/header.html
<head><title>Foo Site</title></head>
templates/bar/header.html
现在为这些文件赋予唯一的模板名称,您可以将内容更改为此:
<head><title>Bar Site</title></head>
templates/foo/header.html
{{ define "foo/header" }}
<head><title>Foo Site</title></head>
{{ end }}
templates/bar/header.html
执行此操作后,您可以直接使用{{ define "bar/header" }}
<head><title>Bar Site</title></head>
{{ end }}
执行它们,也可以使用t.ExecuteTemplate(w, "foo/header", nil)
操作让其他模板间接引用它们。
解析时需要更改模式字符串:
{{ template "bar/header" . }}