go - 如何在子目录中加载模板

标签 go go-templates

我目前将所有html文件保存在一个平面目录templates/中,并使用

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

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

例子
{{ template "navbar" }}

会成为
{{ template "components/navbar" }}

有点困惑...

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

最佳答案

Go's 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 creates a new Template and parses the template definitions from the named files. The returned template's name will have the (base) name and (parsed) contents of the first file. There must be at least one file. If an error occurs, parsing stops and the returned *Template is nil.

When parsing multiple files with the same name in different directories, the last one mentioned will be the one that results. For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template named "foo", while "a/foo" is unavailable.



这意味着,如果要加载所有文件,则必须至少确保以下两项:(1)每个文件的基本名称在所有模板文件中都是唯一的,而不仅仅是在文件所在的目录中,或(2)使用文件内容顶部的{{ define "<template_name>" }}操作为每个文件提供唯一的模板名称(并且不要忘记{{ end }}来关闭define操作)。

作为第二种方法的示例,假设您的模板中有两个具有相同基本名称的文件,例如templates/foo/header.htmltemplates/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" . }}操作引用它们来间接执行它们。

关于go - 如何在子目录中加载模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60898254/

相关文章:

unmarshaljson 中的 golang 类型转换

go - ExecuteTemplate (template.ParseGlob) 加载空白页

go - golang 模板中字符串 slice 的范围

google-chrome - 当我从 chrome websocket 发送 127+ 个字符时,我的 golang 服务器不能看到超过 126 个

go - 版本不匹配的 VSCode Golang dlv 调试错误

if-statement - 如何在HTML属性中插入if语句?

templates - Golang 模板引擎管道

go - 无法评估字符串类型的字段 <field>

go - 痛饮 + 去 : unsupported relocation for dynamic symbol

c++ - 用 Go 构建包装 C++