如何在子目录中加载模板

问题描述 投票:0回答:2

我目前将我所有的html文件都放在一个平面目录templates/中,并使用以下方式加载所有内容

tmpl := template.Must(template.ParseGlob("templates/*.html"))

但是我现在想引入一些结构并将模板放入文件夹componentsbase等中。但是当我这样做时,我的网站将停止工作。我认为可能是上述情况,还是我需要引用模板中的路径?

示例

{{ template "navbar" }}

将成为

{{ template "components/navbar" }}

有点困惑...

我现在还使用本机go库而不是框架。

go go-templates
2个回答
1
投票

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 }}操作)。


作为第二种方法的示例,假设您的模板中有两个具有相同基本名称的文件,例如definetemplates/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)操作让其他模板间接引用它们。


0
投票

解析时需要更改模式字符串:

{{ template "bar/header" . }}
© www.soinside.com 2019 - 2024. All rights reserved.