如何修改Golang嵌套模板中的内容?
如何修改Golang嵌套模板中的内容? 我有一个主布局,想要在其中填充多个子页面。同时我还尝试动态更改这些内容。
代码按预期运行,但我无法更改内容。无论传递什么模板,内容都保持不变。似乎总是获取第一个匹配项。即使使用硬编码的文件名也不起作用。
主布局
{{define "layout"}}
<html>
<body>
{{ template "content" }}
</body>
</html>
{{end}}
子模板1 - index.gohtml
{{ define "content" }}
<h1 style="color: red;">Page 1!</h1>
{{ end }}
子模板2 - about.gohtml
{{ define "content" }}
<h1 style="color: blue;">Page 2!</h1>
{{ end }}
Go代码
package main
import (
"html/template"
"net/http"
"strings"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(r.URL.Path, "/")
switch path {
case "":
path = ("index.gohtml")
default:
path = (path + ".gohtml")
}
err := tpl.ExecuteTemplate(w, "layout", path)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
我也尝试过在执行前使用ParseFiles,但没有成功。有什么建议可以解决这个问题吗?
更多关于如何修改Golang嵌套模板中的内容?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这是你想要实现的目标吗?
https://www.htmlgoodies.com/beyond/reference/nesting-templates-with-go-web-programming.html
更多关于如何修改Golang嵌套模板中的内容?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
是的。一个布局包含多个不同的模板。
这段代码可以正常工作:
var tpl *template.Template
func init() {tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
tpl.ExecuteTemplate(w, "layout", nil)
}
但是当我尝试设置其他内容时:
var tpl *template.Template
func init() {tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
tpl, _ = template.ParseFiles("layout.gohtml", "index.gohtml")
tpl.ExecuteTemplate(w, "layout", nil)
}
出现了大量错误:
http: panic serving 127.0.0.1:52020: runtime error: invalid memory address or nil pointer dereference etc
所以欢迎提供任何建议!
问题在于你的代码中使用了错误的模板执行方法。ExecuteTemplate 的第三个参数应该是数据对象,而不是模板名称。你需要修改执行逻辑来正确选择子模板。
以下是修正后的代码:
Go代码
package main
import (
"html/template"
"net/http"
"strings"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(r.URL.Path, "/")
if path == "" {
path = "index"
}
// 重新解析模板以确保获取最新的模板定义
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
// 直接执行对应的内容模板
err := tpl.ExecuteTemplate(w, path, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
或者,如果你想要保持布局结构,可以使用关联模板的方法:
package main
import (
"html/template"
"net/http"
"strings"
)
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(r.URL.Path, "/")
if path == "" {
path = "index"
} else {
path = path + ".gohtml"
}
// 动态解析布局和对应的内容模板
tpl := template.Must(template.ParseFiles("templates/layout.gohtml", "templates/"+path))
err := tpl.ExecuteTemplate(w, "layout", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
另一个更简洁的解决方案是使用模板组合:
package main
import (
"html/template"
"net/http"
"strings"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
func index(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(r.URL.Path, "/")
var templateName string
switch path {
case "":
templateName = "index"
case "about":
templateName = "about"
default:
templateName = "index"
}
// 重新解析所有模板
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
err := tpl.ExecuteTemplate(w, templateName, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
主要问题是模板解析和执行逻辑不正确。第一个解决方案直接执行内容模板,第二个解决方案动态组合布局和内容模板,第三个解决方案通过重新解析确保模板定义是最新的。


