0
点赞
收藏
分享

微信扫一扫

Go 组合模板

这一期我们讲讲 Go 组合模板,组合模板一般用于 Layout (布局),很多文本结构其实非常固定,例如网页有首部、正文和尾部等。首先介绍一下 Layout 模板, Layout 模板就是网页中固定的部分,它可以被多个网页重复使用。

在 Action 中我们曾提到包含类 Action ,它允许你在模板中包含其它的模板:

{{ template "name" arg }}

但以这种方式做 Layout 模板是不可行的,我们应该在模板文件里面使用 ​​{{ define action }}​​ 再定义一个模板。下面讲一个例子:

首先我们写一个 home.html 文件,这里我们使用了 ​​define action​​​ 定义了一个模板,该模板名为 ​​content​​ :

{{ define "content" }}
<h1>Home</h1>
<h1>{{ . }}</h1>
{{ end }}

然后我们写一个 layout.html 文件,这里使用了 ​​define action​​​ 定义了一个模板,该模板名为 ​​layout​​​ ,该模板使用包含类 Action 包含 ​​content​​ 模板:

{{ define "layout" }}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Layout</title>
</head>
<body>
<h1>Layout</h1>
{{ template "content" . }}
</body>
</html>

{{ end }}

最后我们在 main.go 中使用 ​​ParseFiles​​​ 函数解析了这两个模板,然后使用 ​​ExecuteTemplate​​ 执行模板,注意,传入的模板名参数是我们定义的模板名参数:

package main

import (
"html/template"
"net/http"
)

func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/home", func (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("home.html", "layout.html")
t.ExecuteTemplate(w, "layout", "Go!")
})
server.ListenAndServe()
}

运行程序并访问 ​​http://localhost:8080/home​​ 我们能看到以下结果:

Layout
Home
Go!

上面就是制作 Layout 模板的例子,当然,我们也可以在多个模板文件里,定义同名的模板。下面是一个例子:

我们在上面例子的基础上添加一个 about.html 文件,这里我们还是使用 ​​define action​​​ 定义了一个模板,该模板名为 ​​content​​ ,模板名与 home.html 一致:

{{ define "content" }}
<h1>About</h1>
{{ end }}

然后我们再对 main.go 进行修改:

package main

import (
"html/template"
"net/http"
)

func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/home", func (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("home.html", "layout.html")
t.ExecuteTemplate(w, "layout", "Go!")
})
http.HandleFunc("/about", func (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("about.html", "layout.html")
t.ExecuteTemplate(w, "layout", "")
})
server.ListenAndServe()
}

运行程序并访问 ​​http://localhost:8080/home​​ 我们同样能看到以下结果:

Layout
Home
Go!

访问 ​​http://localhost:8080/about​​ 我们能看到以下结果:

Layout
About

这个就是定义同名的模板并解析的例子。

下面讲 ​​block action​​​ ,使用 ​​block action​​ 可以定义默认模板,其形式如下:

{{ block "name" arg }}
Dot is set to arg
{{ end }}

它等价于定义一个模板,然后立马使用:

{{ define "name" }}
some content
{{ end }}

{{ template "name" arg }}

这里要注意, ​​template​​​ 后面跟的模板必须可用,而 ​​block​​ 后面跟的模板可以不存在,因为它首先会定义一个模板然后再使用。下面是一个例子,这个例子还是基于上面的例子,首先修改 layout.html 如下:

{{ define "layout" }}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Layout</title>
</head>
<body>
<h1>Layout</h1>
{{ block "a" . }}
Contact
{{ end }}
</body>
</html>

{{ end }}

可以看到, ​​block​​ 后面跟的模板是不存在的,但它会定义一个模板然后再使用。下面是 main.go 文件,我们增加了一个 Handler ,这个 Handler 只解析上面的 layout.html 文件:

package main

import (
"html/template"
"net/http"
)

func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/home", func (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("home.html", "layout.html")
t.ExecuteTemplate(w, "layout", "Go!")
})
http.HandleFunc("/about", func (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("about.html", "layout.html")
t.ExecuteTemplate(w, "layout", "")
})
http.HandleFunc("/contact", func (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("layout.html")
t.ExecuteTemplate(w, "layout", "")
})
server.ListenAndServe()
}

访问 ​​http://localhost:8080/contact​​ 我们能看到以下结果:

Layout
Contact

但如果你修改 layout.html ,把 ​​block​​​ 改为 ​​template​​​ 就不会有 ​​Contact​​​ 的输出,而且如果你打印 ​​ExecuteTemplate​​ 返回的错误信息,会有找不到模板错误的日志。




举报

相关推荐

0 条评论