Go语言零到一:模板引擎(go模板函数)
引言
在 Go 语言中,html/template 包提供了一种强大而灵活的方式来生成 HTML 输出。通过模板,你可以轻松地将数据结构嵌入到 HTML 文档中,从而根据不同的输入数据动态生成不同的输出结果。
1. 基础概念
1.1 模板
模板是一个文本文件,其中包含了静态内容和动态占位符。当模板被渲染时,动态占位符会被实际的数据替换。
1.2 动作
动作是由模板引擎执行的操作,通常以双大括号 {{ }} 包围。常见的动作包括条件判断、循环等。
1.3 管道
管道 | 用于连接多个动作,使一个动作的结果作为下一个动作的输入。
2. 模板语法
2.1 变量
变量可以用来存储数据,比如 {{ .Name }} 将会渲染为变量 Name 的值。
2.2 控制结构
- 条件判断:{{ if .Age }}...{{ end }} 根据 .Age 是否存在来决定是否渲染内部内容。
- 循环:{{ range .Posts }}...{{ end }} 对 .Posts 列表中的每一项执行内部模板。
2.3 功能函数
- HTML 转义:{{ .Name | html }} 自动转义 HTML 特殊字符。
- 其他内置函数:len, index, print, printf, println 等。
3. 创建模板
假设我们有一个简单的用户信息页面user_info.html,需要显示用户名、年龄和一篇博客文章列表:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ .Name }}'s Blog</title>
</head>
<body>
<h1>Welcome {{ .Name }}</h1>
<p>Age: {{ .Age }}</p>
<ul>
{{ range .Posts }}
<li><a href="/post/{{ .ID }}">{{ .Title }}</a></li>
{{ end }}
</ul>
</body>
</html>
4. 在 Go 中使用模板
4.1 加载模板
使用 template.Must(template.ParseFiles("path/to/file.html")) 来加载模板文件。
4.2 渲染模板
通过调用 Execute 方法将数据传递给模板并渲染输出。
5. 示例代码
结合前面的内容,下面是一个完整的示例,展示了如何使用 html/template 包来渲染一个简单的用户信息页面,并使用中间件来记录日志。
package main
import (
"html/template"
"log"
"net/http"
"time"
)
type User struct {
Name string
Age int
Posts []Post
}
type Post struct {
ID int
Title string
}
func handleUserPage(w http.ResponseWriter, r *http.Request) {
user := User{
Name: "Alice",
Age: 25,
Posts: []Post{
{ID: 1, Title: "Hello World"},
{ID: 2, Title: "Go is Fun"},
},
}
tmpl, err := template.ParseFiles("user_info.html")
if err != nil {
http.Error(w, "Template parsing error", http.StatusInternalServerError)
log.Println(err)
return
}
err = tmpl.Execute(w, user)
if err != nil {
http.Error(w, "Template execution error", http.StatusInternalServerError)
log.Println(err)
return
}
}
func loggerMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
})
}
func main() {
router := http.NewServeMux()
router.HandleFunc("/", handleUserPage)
handler := loggerMiddleware(router)
log.Println("Starting server on :8080...")
http.ListenAndServe(":8080", handler)
}