1.模板继承
用于统一继承导航栏、页脚等公有部分,通过block、define、template实现模板继承。
base.tmpl
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .head{height: 50px; background-color: red;width: 100%;text-align: center;} .main{width: 100%;} .main .left{width: 30%;height: 1000px;float: left;background-color:violet;text-align: center;} .main .right{width: 70%;float: left;text-align: center;height: 1000px;background-color:yellowgreen;} </style> </head> <body> <div class="head"> <h1>head</h1> </div> <div class="main"> <div class="left"> <h1>side</h1> </div> <div class="right"> {{ block "content" . }} <h1>content</h1> {{ end }} </div> </div> </body> </html>
index.tmpl
{{ template "base.tmpl" . }} {{ define "content" }} <h5>这是index页面</h5> {{ . }} {{ end }}
home.tmpl
{{ template "base.tmpl" . }} {{ define "content" }} <h5>这是home页面</h5> {{ . }} {{ end }}
main.go
package main import ( "html/template" "net/http" ) func indexHandleFunc(w http.ResponseWriter, r *http.Request) { t := template.New("index.tmpl") t, _ = t.ParseFiles("./base.tmpl", "./index.tmpl") t.Execute(w, "index") } func homeHandleFunc(w http.ResponseWriter, r *http.Request) { t := template.New("home.tmpl") t, _ = t.ParseFiles("./base.tmpl", "./home.tmpl") t.Execute(w, "home") } func main() { server := http.Server{ Addr: "localhost:8080", } http.HandleFunc("/index", indexHandleFunc) http.HandleFunc("/home", homeHandleFunc) server.ListenAndServe() }
2.修改默认的标识符
Go标准库的模板引擎使用的花括号{{和}}作为标识,而许多前端框架(如Vue和 AngularJS)也使用{{和}}作为标识符,所以当同时使用Go语言模板引擎和以上前端框架时就会出现冲突,需要修改标识符,修改前端的或者修改Go语言的。这里演示如何修改Go语言模板引擎默认的标识符:
template.New("test").Delims("{[", "]}").ParseFiles("./t.tmpl")
3.html/template的上下文感知
对于html/template包,有一个很好用的功能:上下文感知。text/template没有该功能。上下文感知具体指的是根据所处环境css、js、html、url的path、url的query,自动进行不同格式的转义。
3.1index.tmpl
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div>{{ . }}</div> </body> </html>
4.2main.go
package main import ( // "text/template" "html/template" "net/http" ) func indexHandleFunc(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("./index.tmpl") data := `<script>alert("helloworld")</script>` t.Execute(w, data) } func main() { http.HandleFunc("/", indexHandleFunc) http.ListenAndServe(":8080", nil) }
运行程序,页面显示:<script>alert("helloworld")</script>
默认是不转义
转义,即编写自定义函数输出javaScript内容
不想转义的话,可以自行编写一个safe函数,手动返回一个template.HTML类型的内容
index.tmpl
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div>{{ .str1 }}</div> <div>{{ .str2 | safe }}</div> </body> </html>
main.go
package main import ( // "text/template" "html/template" "net/http" ) func indexHandleFunc(w http.ResponseWriter, r *http.Request) { t := template.New("index.tmpl") t.Funcs(template.FuncMap{ "safe": func(str string) template.HTML { return template.HTML(str) }, }).ParseFiles("./index.tmpl") m := map[string]interface{}{ "str1": `<script>alert("helloworld")</script>`, "str2": `<a href = "http://baidu.com">baidu</a>`, } t.Execute(w, m) }
4.go:embed打包静态资源
4.1未用go:embed打包
package main import ( "log" "net/http" ) func main() { mux := http.DefaultServeMux mux.Handle("/web/js/", http.StripPrefix("/web/js/", http.FileServer(http.Dir("static/js/")))) mux.Handle("/web/css/", http.StripPrefix("/web/css/", http.FileServer(http.Dir("static/css/")))) mux.Handle("/web/img/", http.StripPrefix("/web/img/", http.FileServer(http.Dir("static/img/")))) log.Fatal(http.ListenAndServe(":8080", mux)) }
说明:static/js表示物理目录,浏览器访问http://localhost:8080/web/js/test.js即可访问到对应文件。
4.2用go:embed
Project structure
go.mod main.go static/css/main.css templates/index.html.tmpl title.txt
main.go
package main import ( "embed" "html/template" "log" "net/http" ) // The go embed directive statement must be outside of function body // Embed the file content as string. //go:embed title.txt var title string // Embed the entire directory. //go:embed templates var indexHTML embed.FS //go:embed static var staticFiles embed.FS func main() { // Note the call to ParseFS instead of Parse t, err := template.ParseFS(indexHTML, "templates/index.html.tmpl") if err != nil { log.Fatal(err) } // http.FS can be used to create a http Filesystem var staticFS = http.FS(staticFiles) fs := http.FileServer(staticFS) // Serve static files http.Handle("/static/", fs) // Handle all other requests http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { var path = req.URL.Path log.Println("Serving request for path", path) w.Header().Add("Content-Type", "text/html") // respond with the output of template execution t.Execute(w, struct { Title string Response string }{Title: title, Response: path}) }) log.Println("Listening on :3000...") // start the server err = http.ListenAndServe(":3000", nil) if err != nil { log.Fatal(err) } }
index.html.tmpl
<html> <head> <title>{{.Title}}</title> <link rel="stylesheet" href="static/css/main.css"> </head> <body> <p>{{.Response}}</p> <p>Powered by // go:embed</p> </body> </html>
title.txt
This is the title.