模板引擎
Logic-less template engines
无逻辑模板引擎,Embedded logic template engines
嵌入逻辑模板引擎
简单的模板
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Go Web Programming</title>
</head>
<body>
{{ . }}
</body>
</html>
goweb模板引擎需要两个步骤,1对文本的模板源进行语法分析,创建一个经过语法分析的模板结构,其中模板源可以是一个字符串,也可以是模板文件包含的内容;(2)经过执行语法分析的模板,将ResponseWriter和模板所需的动态数据传给模板引擎,被调用的模板引擎会把经过语法分析的模板和传入的数据结合起来生成,最终的HTML
- 分析模板
package main
import (
"html/template"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
// ParseFiles是一个标准函数,他对模板文件进行语法分析
// 并创建出一个Execute()方法执行,
// ParseFiles函数 只是为了 方便调用Template结构的ParseFiles而设置个一个函数
t, _ := template.ParseFiles("tmpl.html")
t.Execute(w, "Hello World!")
}
func main() {
server := http.Server{Addr: "127.0.0.1:8081"}
http.HandleFunc("/tem", process)
server.ListenAndServe()
}
效果相同
t, _ := template.ParseFiles("tmpl.html")
and
tmpl := `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Go Web Programming</title>
</head>
<body>
{{ . }}
</body>
</html>
`
t := template.New("tmpl.html")
t, _ = t.Parse(tmpl)
t.Execute(w, "Hello World!")
t , err := template.Must(template.ParseFiles("tmpl.html"))
template.Must 函数可以检测模板分析是否有错误
执行模板
t.Execute(w, "Hello World!")
单个文件; t.ExecuteTemplate(w, "t2.html", "Hello World!")多个文件
动作
- 条件动作
- 迭代动作
- 设置动作
- 包含动作
条件动作
{{ if arg }}
some content
{{ end }}
The other variant is
{{ if arg }}
some content
{{ else }}
other content
{{ end }}
tmpl.html
<body>
{{ if . }}
Number is greater than 5!
{{ else }}
Number is 5 or less!
{{ end }}
</body>
package main
import (
"html/template"
"math/rand"
"net/http"
"time"
)
func process(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("tmpl.html")
rand.Seed(time.Now().Unix())
t.Execute(w, rand.Intn(10) > 5)
}
func main() {
server := http.Server{Addr: "127.0.0.1:8081"}
http.HandleFunc("/tem", process)
server.ListenAndServe()
}
"."
可以对数组,slice,map或者channel进行迭代,而在迭代循环的内部,点(.)则会设置为当前被迭代的元素,like:
{{ range array }}
列表元素 {{ . }}
{{ end }}
使用示例
<ul>
{{ range . }}
<li>{{ . }}</li>
{{ end}}
</ul>
// -----go代码 ----
func process(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("tmpl.html")
daysOfWeek := []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
t.Execute(w, daysOfWeek)
}
默认值
<ul>
{{ range . }}
<li>{{ . }}</li>
{{ else }}
<li> Nothing to show </li>
{{ end}}
</ul》
设置动作
{{ with arg }}
Dot is set to arg
{{ end }}
example
<!-- html -->
<div>The dot is {{ . }}</div>
<div>
{{ with "world" }}
Now the dot is set to {{ . }}
{{ end }}
</div>
<div>The dot is {{ . }} again</div>
// ---- go ---
func process(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("tmpl.html")
t.Execute(w,"hello")
}
/*
{{ with "world" }} 之前的点会因为处理器传入的值而被设置成hello;
而位于{{ with "world" }}和{{end}}之间的点则会被设置成world;
但是之后{{.}}值又重新会被设置成hello
*/
{{ with arg }}
Dot is set to arg
{{ else }}
Fallback if arg is empty
{{ end }}
/*
with 也有设置默认值
*/
include action
模板嵌套模板
{{ template "name" }} 其中name参数为被包含模板的名字
t1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=9">
<title>Go Web Programming</title>
</head>
<body>
<div> This is t1.html before</div>
<div>This is the value of the dot in t1.html - [{{ . }}]</div>
<hr/>
{{ template "t2.html" }}
<hr/>
<div> This is t1.html after</div>
</body>
</html>
t2.html
<div style="background-color: yellow;">
This is t2.html<br/>
This is the value of the dot in t2.html - [{{ . }}]
</div>
- 嵌套模板的调用
func process(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("t1.html", "t2.html")
t.Execute(w, "hello World!")
}
/*
数据并不会传入包含的模板
*/
被包含的模板也进行数据渲染 {{ template "t2.html" . }}
参数变量和管道
{{ if arg }}
some content
{{end}}
$variable := value
{{range $key,$value := . }}
the key is {{$key}} and the value is {{$value}}
{{end}}
{{p1|p2|p3}}
<body>
{{12.3456 | printf "%.2f" }}
</body>
函数
package main
import (
"html/template"
"net/http"
"time"
)
func formatDate(t time.Time) string {
layout := "2006-01-02"
return t.Format(layout)
}
func process(w http.ResponseWriter, r *http.Request) {
funcMap := template.FuncMap{"fdate": formatDate} // fdate 将此函数名设置到模板中
t := template.New("tmpl.html").Funcs(funcMap)
t, _ = t.ParseFiles("tmpl.html")
t.Execute(w, time.Now())
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
// ----- html ---
通过管道使用自定义函数
<body>
<div>The date/time is {{ . | fdate }}</div>
</body>
参数传递的方式使用自定义函数
<div>The date/time is {{ fdate . }}</div>
上下文处理器
<body>
<div>{{ . }}</div>
<div><a href="/{{ . }}">Path</a></div>
<div><a href="/?q={{ . }}">Query</a></div>
<div><a onclick="f('{{ . }}')">Onclick</a></div>
</body>
package main
import "net/http"
import "html/template"
func process(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("tmpl.html")
content := `I asked: <i>"What's up?"</i>`
t.Execute(w, content)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
输出
<body>
<div>I asked: <i>"What's up?"</i></div>
<div><a href="/I%20asked:%20%3ci%3e%22What%27s%20up?%22%3c/i%3e">Path</a></div>
<div><a href="/?q=I%20asked%3a%20%3ci%3e%22What%27s%20up%3f%22%3c%2fi%3e">Query</a></div>
<div><a onclick="f('I asked: x3cix3ex22Whatx27s up?x22x3c/ix3e')">Onclick</a></div>
</body>
I asked: <i>"What's up?"</i>
Path
Query
Onclick
模板嵌套
{{ define "layout" }}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Go Web Programming</title>
</head>
<body>
{{ template "content" }}
</body>
</html>
{{ end }}
{{ define "content" }}
Hello World!
{{ end }}
// --- go ---
package main
import "net/http"
import "html/template"
func process(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("layout.html")
t.ExecuteTemplate(w, "layout", "")
// 需要显示的使用 ExecuteTemplate;
// layout作为参数 因为layout模板嵌套了content模板;所以程序只需要执行layout模板就可以
// 在浏览器中得到content模板产生的hello world输出
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
example点击切换模板
red_hello.html
{{ define "content" }}
<h1 style="color: red">
Hello World!
</h1>
{{ end }}
bule_hello.html
{{ define "content" }}
<h1 style="color: burlywood">
Hello World!
</h1>
{{ end }}
package main
import "net/http"
import (
"html/template"
"math/rand"
"time"
)
func process(w http.ResponseWriter, r *http.Request) {
rand.Seed(time.Now().Unix())
var t *template.Template
if rand.Intn(10) > 5 {
// 根据随机数进行语法解析选择哪个模板文件
t, _ = template.ParseFiles("layout.html", "red_hello.html")
} else {
t, _ = template.ParseFiles("layout.html", "bule_hello.html")
}
t.ExecuteTemplate(w, "layout", "")
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}