经过如下文章,掌握了 Go 模板引擎 的基本用法:php
但在开始学习 Beego 框架的 模板嵌套 模块源码时,有点似懂非懂的感受。认真研究了一段时间,总算搞懂了 其本质的原理:html
一、Beego 底层用的是 Go 自带的模板引擎,所以,只须要继续研究 Go 自带的 模板嵌套 的使用方法便可;mvc
二、主要涉及到 4 个模板方法:New()、Parse()、Lookup()、Execute(),先看几个例子:框架
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`我是mod2`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl.Execute(os.Stdout, nil) fmt.Println("\n++++++++++++++++") fmt.Println(tpl.Name())
输出:学习
我是mod3 ++++++++++++++++ mod3
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`我是mod2`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl2 := tpl.Lookup("mod2") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
输出:spa
我是mod2
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_标题{{end}}我是mod2_内容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl2 := tpl.Lookup("mod2") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
输出:htm
我是mod2_内容
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_标题{{end}}我是mod2_内容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl2 := tpl.Lookup("Title") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
输出:对象
我是mod2_标题
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_标题{{end}}我是mod2_内容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3`) tpl = tpl.New("mod4") tpl, _ = tpl.New("mod5").Parse("我是mod5") fmt.Println(tpl.Name()) fmt.Println("+++++++++++++++") tpl2 := tpl.Lookup("mod4") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) } tpl3 := tpl.Lookup("mod5") if tpl3 != nil { tpl3.Execute(os.Stdout, nil) }
输出:blog
mod5 +++++++++++++++ 我是mod5
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_标题{{end}}我是mod2_内容`) tpl, _ = tpl.New("mod1").Parse(`我是mod1_内容{{define "Title"}}我是mod1_标题{{end}}`) fmt.Println(tpl.Name()) fmt.Println("+++++++++++++++") tpl2 := tpl.Lookup("mod1") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) } fmt.Println("\n+++++++++++++++") tpl3 := tpl.Lookup("Title") if tpl3 != nil { tpl3.Execute(os.Stdout, nil) }
输出:模板引擎
mod1 +++++++++++++++ 我是mod1_内容 +++++++++++++++ 我是mod1_标题
tpl, _ := template.New("mod1").Parse(`我是mod1`) tpl, _ = tpl.New("mod2").Parse(`{{define "Title"}}我是mod2_标题{{end}}我是mod2_内容`) tpl, _ = tpl.New("mod3").Parse(`我是mod3_{{template "mod1"}}_{{template "Title"}}`) tpl2 := tpl.Lookup("mod3") if tpl2 != nil { tpl2.Execute(os.Stdout, nil) }
输出:
我是mod3_我是mod1_我是mod2_标题
一、一个模板对象,能够有多个“名称”,可是经过 .Name() 方法,只返回最后一次经过 .New() 方法新建的“名称”。特别注意:此时的 模板对象 的 数据段也是指向该“名称”所绑定的“字符串”数据;
二、一个模板对象,能够有多个“名称”,可是他们是相互独立的,每一个“名称”,经过 .Parse() 方法,能够与一段“字符串”数据对象创建关联。也就是说,后期经过 .Lookup("某个名称") 方法获取到的(模板)对象,其当前数据段,指向该“字符串”,再经过 .Execute() 方法输出的内容,也是跟该“字符串”相关的内容;
三、在某个“名称”的数据“字符串”对象中,能够用 define 定义子模块名,如 {{define "子模块名"}}子模块内容{{end}},该 “子模块”又独立于 当前“名称”,即 当前“名称”的输出内容,不包含 “子模板”的内容,参考 示例3
只输出“我是mod2_内容”,并无输出“我是mod2_标题”
四、特别注意,经过 {{define "子模块名"}}子模块内容{{end}} 定义的名称,并非 模板对象 的一个“名称”,可是咱们一样能够用 .Lookup("某个名称") 方法获取到对象,其当前数据段,指向该 “子模块”,再经过 .Execute() 方法输出的内容,也是跟该“子模块”相关的内容,查看 示例4
只输出“我是mod2_标题”
五、可用重复定义“名称”和 “子模块”,但后面定义的会覆盖前面定义的,即 只有最后一次定义的有效。参考 示例6
六、模板内容(“名称”的“字符串”对象)中,可经过 template 关键字来 引用/包含 “名称”和 “子模块”,如 {{template "名称/子模块"}},参考 示例7
搞明白了这些基础知识,再回过头看 Beego 的模板模块,已经是很是简单了!