Golang中如何构建头部和基础模板
Golang中如何构建头部和基础模板 我正在开始学习Go语言,在寻找成熟的Web框架之前,先看了一下Web开发(内置功能)。我看到了关于模板的内容:
<h1>{{.PageTitle}}</h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>
这是由下面的Go代码加载的:
package main
import (
"html/template"
"net/http"
)
type Todo struct {
Title string
Done bool
}
type TodoPageData struct {
PageTitle string
Todos []Todo
}
func main() {
tmpl := template.Must(template.ParseFiles("layout.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := TodoPageData{
PageTitle: "My TODO list",
Todos: []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
},
}
tmpl.Execute(w, data)
})
http.ListenAndServe(":80", nil)
}
我的问题是:
如何同时加载两个模板,比如一个base模板和一个index模板,这样无论加载的是索引页还是其他页面,基础模板都保持不变。
类似于PHP中的[header](https://www.php.net/manual/en/function.header.php)
<html>
<?php
/* This will give an error. Note the output
* above, which is before the header() call */
header('Location: http://www.example.com/');
exit;
?>
或者Django中的[extending](https://tutorial.djangogirls.org/en/template_extending/)
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h2><a href="">{{ post.title }}</a></h2>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
{% endblock %}
更多关于Golang中如何构建头部和基础模板的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
在Go语言中,可以通过模板组合和继承来实现头部和基础模板。以下是几种常见的方法:
方法1:使用template.ParseFiles加载多个模板
package main
import (
"html/template"
"net/http"
)
func main() {
// 加载多个模板文件
tmpl := template.Must(template.ParseFiles("base.html", "index.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"Title": "首页",
"Content": "这是首页内容",
}
// 执行特定的模板
tmpl.ExecuteTemplate(w, "index.html", data)
})
http.ListenAndServe(":8080", nil)
}
方法2:使用模板继承(类似Django)
base.html(基础模板):
<!DOCTYPE html>
<html>
<head>
<title>{{block "title" .}}默认标题{{end}}</title>
<style>
body { font-family: Arial, sans-serif; }
.header { background: #333; color: white; padding: 10px; }
.content { padding: 20px; }
</style>
</head>
<body>
<div class="header">
<h1>{{block "header" .}}网站标题{{end}}</h1>
</div>
<div class="content">
{{block "content" .}}默认内容{{end}}
</div>
<div class="footer">
{{block "footer" .}}© 2023 我的网站{{end}}
</div>
</body>
</html>
index.html(继承基础模板):
{{define "title"}}首页 - 我的网站{{end}}
{{define "header"}}欢迎来到首页{{end}}
{{define "content"}}
<h2>最新文章</h2>
<ul>
{{range .Articles}}
<li>{{.Title}} - {{.Date}}</li>
{{end}}
</ul>
{{end}}
{{define "footer"}}
<p>© 2023 我的网站 | 联系: contact@example.com</p>
{{end}}
Go代码:
package main
import (
"html/template"
"net/http"
"time"
)
type Article struct {
Title string
Date time.Time
}
func main() {
// 加载所有模板
tmpl := template.Must(template.ParseFiles("base.html", "index.html", "about.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"Articles": []Article{
{Title: "Go语言入门", Date: time.Now().AddDate(0, 0, -2)},
{Title: "模板使用指南", Date: time.Now().AddDate(0, 0, -1)},
{Title: "Web开发实践", Date: time.Now()},
},
}
// 执行基础模板,它会自动包含index.html中定义的块
tmpl.ExecuteTemplate(w, "base.html", data)
})
http.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"Title": "关于我们",
}
tmpl.ExecuteTemplate(w, "base.html", data)
})
http.ListenAndServe(":8080", nil)
}
方法3:使用模板包含(Include)
header.html:
<header>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
<a href="/contact">联系</a>
</nav>
<h1>{{.SiteTitle}}</h1>
</header>
footer.html:
<footer>
<p>版权所有 © {{.Year}} {{.CompanyName}}</p>
</footer>
layout.html:
<!DOCTYPE html>
<html>
<head>
<title>{{.PageTitle}}</title>
</head>
<body>
{{template "header.html" .}}
<main>
{{template "content" .}}
</main>
{{template "footer.html" .}}
</body>
</html>
index.html:
{{define "content"}}
<h2>欢迎</h2>
<p>{{.WelcomeMessage}}</p>
<ul>
{{range .Items}}
<li>{{.}}</li>
{{end}}
</ul>
{{end}}
Go代码:
package main
import (
"html/template"
"net/http"
"time"
)
func main() {
// 使用ParseGlob加载所有模板文件
tmpl := template.Must(template.ParseGlob("templates/*.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"PageTitle": "首页",
"SiteTitle": "我的Go网站",
"CompanyName": "Go科技有限公司",
"Year": time.Now().Year(),
"WelcomeMessage": "欢迎访问我们的网站",
"Items": []string{"产品1", "产品2", "产品3"},
}
tmpl.ExecuteTemplate(w, "layout.html", data)
})
http.ListenAndServe(":8080", nil)
}
方法4:使用模板函数处理通用部分
package main
import (
"html/template"
"net/http"
"strings"
)
func main() {
// 创建模板函数映射
funcMap := template.FuncMap{
"toUpper": strings.ToUpper,
"formatTitle": func(title string) string {
return "MySite - " + title
},
}
// 解析模板并添加函数
tmpl := template.Must(template.New("").Funcs(funcMap).ParseFiles(
"base.tmpl",
"index.tmpl",
"partials/header.tmpl",
"partials/footer.tmpl",
))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := struct {
Title string
Content string
User string
}{
Title: "首页",
Content: "欢迎内容",
User: "访客",
}
// 使用模板布局
err := tmpl.ExecuteTemplate(w, "base.tmpl", data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
http.ListenAndServe(":8080", nil)
}
这些方法展示了Go语言中如何实现模板的复用和继承。template.ParseFiles可以加载多个模板文件,ExecuteTemplate可以指定执行哪个模板,而模板中的{{define}}和{{block}}指令提供了模板继承和覆盖的机制。


