1 模板语法
在一些前后端不分离的Web架构中,我们通常需要在后端将一些数据渲染到HTML文档中,从而实现动态的网页(网页的布局和样式大致一样,但展示的内容并不一样)效果。我们这里说的模板可以理解为事先定义好的HTML文档文件,模板渲染的作用机制可以简单理解为文本替换操作–使用相应的数据去替换HTML文档中事先准备好的标记。
Go语言内置了文本模板引擎text/template和用于HTML文档的html/template。它们的作用机制可以简单归纳如下:
1 模板文件通常定义为.tmpl和.tpl为后缀(也可以使用其他的后缀),必须使用UTF8编码。
2 模板文件中使用{{和}}包裹和标识需要传入的数据。
3 传给模板这样的数据就可以通过点号 ‘.’ 来访问,如果数据是复杂类型的数据,可以通过{ { .FieldName }}来访问它的字段。除{{和}}包裹的内容外,其他内容均不做修改原样输出。
1.1 Hello World
package main
import (
"fmt"
"net/http"
"text/template"
)
func main() {
http.HandleFunc("/hello", hello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err : %v", err)
return
}
}
func hello(w http.ResponseWriter, r *http.Request) {
//解析模板
t, err := template.ParseFiles("./template/html/hello.html")
if err != nil {
fmt.Printf("parse template failed, err: %v n", err)
}
//渲染模板
t.Execute(w, "Hello Template")
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<h1>{{.}}</h1>
</body>
</html>
1.2 解析结构体
package main
import (
"fmt"
"net/http"
"text/template"
)
type User struct {
Name string
Age int
}
func main() {
http.HandleFunc("/hello", hello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err : %v", err)
return
}
}
func hello(w http.ResponseWriter, r *http.Request) {
//解析模板
t, err := template.ParseFiles("./template/html/hello.html")
if err != nil {
fmt.Printf("parse template failed, err: %v n", err)
}
//创建数据
u1 := User{"Kobe", 18}
u2 := User{"James", 18}
rs := map[string]interface{}{
"u1": u1,
"u2": u2,
}
//渲染模板
t.Execute(w, rs)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<h1>姓名:{{.u1.Name}} 年龄:{{.u1.Age}}</h1>
<h1>姓名:{{.u2.Name}} 年龄:{{.u2.Age}}</h1>
</body>
</html>3 解析循环
1.3 解析切片
package main
import (
"fmt"
"net/http"
"text/template"
)
type User struct {
Name string
Age int
}
func main() {
http.HandleFunc("/hello", hello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err : %v", err)
return
}
}
func hello(w http.ResponseWriter, r *http.Request) {
//解析模板
t, err := template.ParseFiles("./template/html/hello.html")
if err != nil {
fmt.Printf("parse template failed, err: %v n", err)
}
//创建数据
u1 := User{"Kobe", 18}
u2 := User{"James", 18}
users := []User{u1, u2}
rs := map[string]interface{}{
"users": users,
"counts": len(users),
}
//渲染模板
t.Execute(w, rs)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
{{if gt .counts 0}}
<p style="color: lightskyblue">展示数据:</p>
{{else}}
<p style="color: lightskyblue">没有数据:</p>
{{end}}
{{range $index,$user := .users}}
<h2 style="color: red"> index:{{$index}}, name:{{$user.Name}}, age:{{$user.Age}} </h2>
{{end}}
</body>
</html>
2 模板嵌套
我们可以在template中嵌套其他的template。这个template可以是单独的文件,也可以是通过define定义的template。
package main
import (
"fmt"
"net/http"
"text/template"
)
type PageInfo struct {
Title string
Content string
}
func main() {
http.HandleFunc("/index", index)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err : %v", err)
return
}
}
func index(w http.ResponseWriter, r *http.Request) {
//定义模板,先模板
t, _ := template.ParseFiles("./template/html/hello.html", "./template/tmpl/head_tmpl.html", "./template/tmpl/foot_tmpl.html")
//数据
data := make(map[string]string)
data["body"] = "Hello GoLang"
data["head"] = "COMMON HEAD"
data["foot"] = "COMMON FOOT"
//渲染
_ = t.ExecuteTemplate(w, "hello.html", data)
}
hello.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
{{template "head_tmpl.html" . }}
{{.body}}
{{template "foot_tmpl.html" . }}
</body>
</html>
head_tmpl.html、foot_tmpl.html:
<div style="height: 200px;width: 100%;background: lightgreen;font-size: 20px;">
{{.head}}
</div>
<div style="height: 200px;width: 100%;background: lightcoral;font-size: 20px;">
{{.foot}}
</div>
3 模板继承
根据官方文档的解释:block等价于define定义一个名为name的模板,并在”有需要”的地方执行这个模板,执行时将”.”设置为pipeline的值。 但应该注意,block的第一个动作是执行名为name的模板,如果不存在,则在此处自动定义这个模板,并执行这个临时定义的模板。换句话说,block可以认为是设置一个默认模板,即父类模板 例如:{{block “T1” .}} one {{end}}。它先找到T1模板,如果T1存在,则执行找到的T1,如果没找到T1,则临时定义一个模板{{define “T1”}} one {{end}},并执行它。 在很多网页中,大体上的布局都差不多,因此可以将布局封装为一个默认模板,以供其他模板调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t0LKMteX-1665390828625)(go web.assets/image-20221010162337728.png)]
package main
import (
"fmt"
"net/http"
"text/template"
)
type PageInfo struct {
Title string
Content string
}
func main() {
http.HandleFunc("/index", index)
http.HandleFunc("/product", product)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err : %v", err)
return
}
}
func product(w http.ResponseWriter, r *http.Request) {
//定义模板,先模板
t, _ := template.ParseFiles("./template/tmpl/base_tmpl.html", "./template/html/product.html")
//渲染数据
pageInfo := PageInfo{"product", "product content"}
//渲染product
_ = t.ExecuteTemplate(w, "product.html", map[string]interface{}{
"pageInfo": pageInfo,
})
}
func index(w http.ResponseWriter, r *http.Request) {
//定义模板,先模板
t, _ := template.ParseFiles("./template/tmpl/base_tmpl.html", "./template/html/index.html")
//渲染数据
pageInfo := PageInfo{"index", "index content"}
//渲染index
_ = t.ExecuteTemplate(w, "index.html", map[string]interface{}{
"pageInfo": pageInfo,
})
}
base_tmpl.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{.pageInfo.Title}}</title>
</head>
<header style="height: 200px;width: 100%;background: lightgreen;font-size: 20px;">
COMMON HEADER
</header>
<body>
<div>
{{block "content" .}} {{end}}
</div>
</body>
<footer style="height: 200px;width: 100%;background: lightcoral;font-size: 20px;">
COMMON FOOTER
</footer>
</html>
index.html:
{{/*继承模板*/}}
{{template "base_tmpl.html" .}}
{{/*重新定义模板*/}}
{{define "content"}}
<h1>这是index页面</h1>
<p> {{.pageInfo.Content}}</p>
{{end}}
product.html:
{{/*继承模板*/}}
{{template "base_tmpl.html" .}}
{{/*重新定义模板*/}}
{{define "content"}}
<h1>这是product页面</h1>
<p> {{.pageInfo.Content}}</p>
{{end}}
原文地址:https://blog.csdn.net/qq_34125999/article/details/127247394
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_51217.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!