Go模板template嵌套与继承 | 青训营笔记

883 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第14天

模板嵌套

自定义函数

func sayHello(w http.ResponseWriter, r *http.Request) {
        htmlByte, err := ioutil.ReadFile("./hello.tmpl")
        if err != nil {
                fmt.Println("read html failed, err:", err)
                return
        }
        // 自定义一个夸人的模板函数
        kua := func(arg string) (string, error) {
                return arg + "真帅", nil
        }
        // 采用链式操作在Parse之前调用Funcs添加自定义的kua函数
        tmpl, err := template.New("hello").Funcs(template.FuncMap{"kua": kua}).Parse(string(htmlByte))
        if err != nil {
                fmt.Println("create template failed, err:", err)
                return
        }
        user := User{
                Name:   "小王子",
                Gender: "男",
                Age:    18,
        }
        // 使用user渲染模板,并将结果写入w
        tmpl.Execute(w, user)
}

或者分开写
//定义模板
t:=template.New("hello.tmpl")
//向模板引擎添加自定义函数
t.Funcs(template.FuncMap{
    "kua":kua,    //"kua"可以写成新的名字
})
//解析模板
_,err:=t.ParseFiles("./hello.tmpl")

我们可以在模板文件hello.tmpl中按照如下方式使用我们自定义的kua函数了。 {{kua .Name}}

嵌套模板template

在template中嵌套其他的template。这个template可以是单独的文件,也可以是通过define定义的template t.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>tmpl test</title>
</head>
<body>
    
    <h1>测试嵌套template语法</h1>
    <hr>
    {{template "ul.tmpl"}}
    <hr>
    {{template "ol.tmpl"}}
</body>
</html>

{{ define "ol.tmpl"}}
<ol>
    <li>吃饭</li>
    <li>睡觉</li>
    <li>打豆豆</li>
</ol>
{{end}}

u1.tmpl

<ul>
    <li>注释</li>
    <li>日志</li>
    <li>测试</li>
</ul>

main函数注册一个tmplDemo路由处理函数: http.HandleFunc("/tmpl", tmplDemo)

func tmplDemo(w http.ResponseWriter, r *http.Request) {
        tmpl, err := template.ParseFiles("./t.tmpl", "./ul.tmpl")
        //被嵌套的模板一定要在后面解析
        if err != nil {
                fmt.Println("create template failed, err:", err)
                return
        }
        user := User{
                Name:   "小明",
                Gender: "男",
                Age:    18,
        }
        tmpl.Execute(w, user)
}

模板继承

block

很多页面的大体布局相同,只有部分区别

{{block "name" pipeline}} T1 {{end}}

block是定义模板{{define "name"}} T1 {{end}}和执行{{template "name" pipeline}}缩写。 典型的用法是定义一组根模板,然后通过在其中重新定义块模板进行自定义。

定义一个根模板templates/base.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>模板继承</title>
</head>
    <style>
        *{
            margin: 0;
        }
        .nav{
            height: 50px;
            width: 100%;
            position: fixed;
            background-color: aqua;
            top: 0;
        }
        .main{
            margin-top: 50px;
        }
        .menu{
            width: 20%;
            height: 100%;
            position: fixed;
            left: 0;
            background-color: aquamarine;
        }
        .center{
            text-align: center;
        }
    </style>
<body>
    <div class="nav"></div>
    <div class="main">
        <div class="menu"></div>
        <div class="content center">
    {{block "content" . }}{{end}}
        </div>
    </div>
</body>
</html>

然后定义一个templates/index.tmpl,”继承”base.tmpl:

{{template "base.tmpl" .}} //.一定要加,继承数据

{{define "content"}}
    <div>Hello world!</div>
    <p>This index</p>
{{end}}

然后使用template.ParseGlob按照正则匹配规则解析模板文件,然后通过ExecuteTemplate渲染指定的模板:

func index(w http.ResponseWriter, r *http.Request){
        //tmpl, err := template.ParseGlob("./*.tmpl")    //全解析
        tmpl, err :=template.ParseFiles("./base.tmpl","./index.tmpl") //选定解析
        if err != nil {
                fmt.Println("create template failed, err:", err)
                return
        }
        msg:="This is index"
        err = tmpl.ExecuteTemplate(w, msg, nil)//指定渲染的模板
        if err != nil {
                fmt.Println("render template failed, err:", err)
                return
        }}

如果我们的模板名称冲突了,例如不同业务线下都定义了一个index.tmpl模板

*1. 在模板文件开头使用{{define 模板名}}语句显式的为模板命名。
*2. 可以把模板文件存放在templates文件夹下面的不同目录中,然后使用template.ParseGlob("templates/**/*.tmpl")解析模板。

修改默认标识符 Go标准库的模板引擎使用的花括号{{和}}作为标识,而许多前端框架(如Vue和 AngularJS)也使用{{和}}作为标识符, 发生冲突

template.New("test").Delims("{[", "]}").ParseFiles("./t.tmpl")

temp,err :=template.New("index.tmpl").Delims("{[","]}").ParseFiles("./index.tmpl")