經過如下文章,掌握了 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 的模板模塊,已經是很是簡單了!