Golang中HTML模板包的使用问题如何解决

Golang中HTML模板包的使用问题如何解决 我有以下代码片段,用于解析模板文件夹中的HTML文件:

func ParseTemplateDir(dir string) (*template.Template, error) {
	var paths []string
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			paths = append(paths, path)
		}
		return nil
	})

	fmt.Println("Am parsing templates...")

	if err != nil {
		return nil, err
	}

	return template.ParseFiles(paths...)
}

以下是我访问特定HTML模板以发送给用户的方式:

var body bytes.Buffer

	template, err := ParseTemplateDir("templates")
	if err != nil {
		log.Fatal("Could not parse template", err)
	}

	// 其中 templateName 可以是 verificationCode.html 或 resetPassword.html
	template = template.Lookup(templateName)
	template.Execute(&body, &data)

golang templates

现在,当我动态访问任何模板时,我总是得到 verificationCode.html 模板。 即使我使用 resetPassword.html 作为模板名称,我仍然得到 verificationCode.html 模板,这很奇怪。 请问我该如何解决这个问题?


更多关于Golang中HTML模板包的使用问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

那么我该如何着手呢?

更多关于Golang中HTML模板包的使用问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


当你重新赋值给 template 时,你正在用查找到的单个模板覆盖你的模板列表。

在查找模板时,不要重新赋值给 template,而是为查找到的模板使用一个不同的名称,或者完全不为查找到的模板赋值,而是执行 template.Lookup(templateName).Execute(&body, &data)

我必须承认,我没有查看文档,我只是假设 ParseFiles 确实会返回一个模板集合。

但情况似乎并非如此,你需要单独解析它们,并将它们整理成一个从文件名/标识符到已解析模板的映射。

func main() {
    fmt.Println("hello world")
}

我尝试了你的方法,但返回的仍然只是第一个解析文件的内容。

我也尝试了以下代码,但问题依旧:

if err := template.ExecuteTemplate(&body, templateName, &data); err != nil {
		log.Fatal("Could not execute template", err)
	}

我认为问题出在 ParseFiles 函数 template.ParseFiles(paths...) 上,因为文档说明它返回的是第一个解析的内容。

问题在于 template.ParseFiles() 返回的模板集合中,第一个模板会成为"主模板"。当你调用 template.Lookup() 时,如果指定的模板名称不存在,它会返回 nil,但你的代码没有检查这个返回值。

以下是修正后的代码:

func ParseTemplateDir(dir string) (*template.Template, error) {
    var paths []string
    err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if !info.IsDir() && strings.HasSuffix(path, ".html") {
            paths = append(paths, path)
        }
        return nil
    })

    if err != nil {
        return nil, err
    }

    // 使用 ParseGlob 或为每个文件创建独立的模板
    return template.ParseFiles(paths...)
}

执行模板的正确方式:

var body bytes.Buffer

tmpl, err := ParseTemplateDir("templates")
if err != nil {
    log.Fatal("Could not parse template", err)
}

// 明确查找模板并检查是否存在
targetTmpl := tmpl.Lookup(templateName)
if targetTmpl == nil {
    log.Fatalf("Template %s not found", templateName)
}

err = targetTmpl.Execute(&body, &data)
if err != nil {
    log.Fatal("Could not execute template", err)
}

或者使用 ExecuteTemplate 方法:

var body bytes.Buffer

tmpl, err := ParseTemplateDir("templates")
if err != nil {
    log.Fatal("Could not parse template", err)
}

// 直接执行指定名称的模板
err = tmpl.ExecuteTemplate(&body, templateName, &data)
if err != nil {
    log.Fatal("Could not execute template", err)
}

调试时可以添加以下代码来查看所有可用的模板:

tmpl, err := ParseTemplateDir("templates")
if err != nil {
    log.Fatal("Could not parse template", err)
}

// 打印所有模板名称
for _, t := range tmpl.Templates() {
    fmt.Printf("Available template: %s\n", t.Name())
}

确保模板文件中的 {{define}} 指令正确:

<!-- verificationCode.html -->
{{define "verificationCode.html"}}
<!DOCTYPE html>
<html>
<body>
    <h1>Verification Code: {{.Code}}</h1>
</body>
</html>
{{end}}

<!-- resetPassword.html -->
{{define "resetPassword.html"}}
<!DOCTYPE html>
<html>
<body>
    <h1>Reset Password</h1>
    <p>Token: {{.Token}}</p>
</body>
</html>
{{end}}

如果模板文件中没有 {{define}} 指令,模板名称将基于文件名。使用 ExecuteTemplate 可以确保执行正确的模板。

回到顶部